You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Next »

Section 6.5.2.5 of the ISO/IEC 9899:1999 (C99) standard defines a compound literal (CL) as:

A postfix expression that consists of a parenthesized type name followed by a brace-enclosed list of initializers ... The value of a compound literal is that of an unnamed object initiated by the initializer list

The storage for this object is either static if the CL occurs at file scope or automatic if the CL occurs at block scope (6.5.2.5.6).

E.g., after the execution of the following line, contained in some arbitrary function:

int *i = (int[4]){1,2,3,4};

the pointer "i" would contain the address of an unnamed object of type "int [4]", allocated on the stack.

It should be noted that only one object is created per CL -- even if the CL appears in a loop and has dynamic initializers (6.5.2.5.16). This can lead to incorrect use, as demonstrated below.

Noncompliant Code Example

In the following example, an array of pointers is filled with what appear to addresses of distinct INT_STRUCT objects, one for each integer in the range [0,MAX_INTS-1]:

typedef struct INT_STRUCT{
  int x;
} INT_STRUCT;

#define MAX_INTS 10
int count(){
  int i;
  INT_STRUCT *ints[MAX_INTS];
  for(i=0;i<MAX_INTS;i++)
    ints[i] = &(INT_STRUCT){i};
  for(i=0;i<MAX_INTS;i++)
    printf("%d\n",ints[i]->x);
}

However, only one INT_STRUCT object is actually created. At each iteration of the first loop, the "x" member of this object is set equal to the current value of the loop counter, "i". Therefore, after the first loop terminates, the value of the "x" member is MAX_INTS-1.

During the print loop, this value is printed MAX_INTS times because every pointer in the "ints" array is set to point to the (single) INT_STRUCT object.

This is contrary to the intuitive expected result, which is that the integers 0 through MAX_INTS-1 would be printed in order.

Compliant Solution

This compliant solution uses an array of structures rather than an array of pointers. That way, an actual copy of each INT_STRUCT (rather than a pointer to the object) is stored.

typedef struct INT_STRUCT{
  int x;
} INT_STRUCT;

#define MAX_INTS 10
int count(){
  int i;
  INT_STRUCT ints[MAX_INTS];
  for(i=0;i<MAX_INTS;i++)
    ints[i] = (INT_STRUCT){i};
  for(i=0;i<MAX_INTS;i++)
    printf("%d\n",ints[i].x);
}

Risk Assessment

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

DCL30

low

unlikely

low

P3

L3

References

[[ISO/IEC 9899:1999|../display/seccode/AA.+References#AA.References-ISO%2FIEC98991999||||\||]] Section 6.5.2.5 (Compound Literals)

  • No labels