Main Content

Misuse of structure with flexible array member

Memory allocation ignores flexible array member

Description

This defect occurs when:

  • You define an object with a flexible array member of unknown size at compilation time.

  • You make an assignment between structures with a flexible array member without using memcpy() or a similar function.

  • You use a structure with a flexible array member as an argument to a function and pass the argument by value.

  • Your function returns a structure with a flexible array member.

A flexible array member has no array size specified and is the last element of a structure with at least two named members.

Risk

If the size of the flexible array member is not defined, it is ignored when allocating memory for the containing structure. Accessing such a structure has undefined behavior.

Fix

  • Use malloc() or a similar function to allocate memory for a structure with a flexible array member.

  • Use memcpy() or a similar function to copy a structure with a flexible array member.

  • Pass a structure with a flexible array member as a function argument by pointer.

Examples

expand all

#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>


struct example_struct
{
    size_t num;
    int data[];
};

extern void arg_by_value(struct example_struct s);

void func(void)
{
    struct example_struct *flex_struct;
    size_t i;
    size_t array_size = 4;
    /* Dynamically allocate memory for the struct */
    flex_struct = (struct example_struct *)
        malloc(sizeof(struct example_struct) + sizeof(int) * array_size);
    if (flex_struct == NULL)
    {
        /* Handle error */    
    }
    /* Initialize structure */
    flex_struct->num = array_size;
    for (i = 0; i < array_size; ++i)
    {
        flex_struct->data[i] = 0;
    }
    /* Handle structure */
	
	/* Argument passed by value. 'data' not 
	copied to passed value. */
    arg_by_value(*flex_struct); 
	
    /* Free dynamically allocated memory */
    free(flex_struct);
}
        
      

In this example, flex_struct is passed by value as an argument to arg_by_value. As a result, the flexible array member data is not copied to the passed argument.

Correction — Pass Structure by Pointer to Function

To ensure that all the members of the structure are copied to the passed argument, pass flex_struct to arg_by_pointer by pointer.

#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>


struct example_struct
{
    size_t num;
    int data[];
};

extern void arg_by_pointer(struct example_struct *s);

void func(void)
{
    struct example_struct *flex_struct;
    size_t i;
    size_t array_size = 4;
    /* Dynamically allocate memory for the struct */
    flex_struct = (struct example_struct *)
        malloc(sizeof(struct example_struct) + sizeof(int) * array_size);
    if (flex_struct == NULL)
    {
        /* Handler error */       
    }
    /* Initialize structure */
    flex_struct->num = array_size;
    for (i = 0; i < array_size; ++i)
    {
        flex_struct->data[i] = 0;
    }
    /* Handle structure */
	
	/* Structure passed by pointer */
    arg_by_pointer(flex_struct); 
	
    /* Free dynamically allocated memory */
    free(flex_struct);
} 

Result Information

Group: Programming
Language: C | C++
Default: On for handwritten code, off for generated code
Command-Line Syntax: FLEXIBLE_ARRAY_MEMBER_STRUCT_MISUSE
Impact: Low

Version History

Introduced in R2017b