Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Some operators do not evaluate their operands beyond the type information the operands provide. When using one of these operators, do not pass an operand that would otherwise yield a side effect since the side effect will not be generated.

The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. When   In most cases, the operand is not evaluated.  A possible exception is when the type of the operand is a variable length array type (VLA); then the expression is evaluated; otherwise, the operand is not evaluated. When part of the operand of the sizeof operator is a VLA type and when changing the value of the VLA's size expression would not affect the result of the operator, it is unspecified whether or not the size expression is evaluated. (See unspecified behavior 22 in Annex J, Section J.1, of the C Standard [ISO/IEC 9899:2011].)

The operand passed to_Alignof is never evaluated, despite not being an expression. For instance, if the operand is a VLA type and the VLA's size expression contains a side effect, that side effect is never evaluated.

The operand used in the controlling expression of a _Generic selection expression is never evaluated.

Providing an expression that appears to produce side effects may be misleading to programmers who are not aware that these expressions are not evaluated, and in the non-VLA case and have case of a VLA used in sizeof, have unspecified results otherwise. As a result, programmers may make invalid assumptions about program state, leading to errors and possible software vulnerabilities.

This rule is similar to PRE31-C. Avoid side effects in arguments to unsafe macros.

Noncompliant Code Example (sizeof)

In this noncompliant code example, the expression a++ is not evaluated, and the side effects in the expression are not executed:

Code Block
bgColor#FFcccc
langc
#include <stdio.h>
 
void func(void) {
  int a = 14;
  int b = sizeof(a++);
  printf("%d, %d\n", a, b);
}

Consequently, the value of a after b has been initialized is 14.

Implementation-Specific Details

This example compiles cleanly under Microsoft Visual Studio 2005, Version 8.0, with the /W4 option.

...

Compliant Solution (sizeof)

In this compliant solution, the variable a is incremented outside of the sizeof operation:

Code Block
bgColor#ccccff
langc
#include <stdio.h>
 
void func(void) {
  int a = 14;
  int b = sizeof(a);
a  ++;

...

a;
  printf("%d, %d\n", a, b);
}

Noncompliant Code Example (

...

sizeof, VLA)

In the following this noncompliant code example, the expression ++n in the initialization expression of a must be evaluated because its value affects the size of the VLA operand of the sizeof operator. However, in the initialization expression of b, because the expression ++n % 1 evaluates to 0, regardless of . This means that the value of n, its value does  does not affect the result of the sizeof operator. Consequently, it is unspecified whether or not n is  will be incremented when initializing b.

Code Block
bgColor#FFcccc
langc
#include <stddef.h>
#include <stdio.h>
  
void f(size_t n) {
  /* n must be incremented */ 
  size_t a = sizeof(int [++n]);       
 
    /* n need mustnot be incremented */
  size_t b = sizeof(int [++n % 1 + 1]);

   /* n need not be incremented */
 printf("%zu, %zu, %zu\n", a, b, n);
  /* ... */
}

...

...

Compliant Solution (

...

sizeof, VLA)

This compliant solution avoids changing the value of the variable n used in the each sizeof expression and instead increments it n safely outside of itafterwards:

Code Block
bgColor#ccccFF
langc
#include <stddef.h>
#include <stdio.h>
  
void f(size_t n) {
  size_t a = sizeof(int [n + 1]);
  ++n;

  size_t b = sizeof(int [n % 1 + 1]);
  ++n;
  printf("%zu, %zu, %zu\n", a, b, n);
  /* ... */
}

Noncompliant Code Example (_Generic)

This noncompliant code example attempts to modify a variable's value as part of the _Generic selection control expression. The programmer may expect that a is incremented, but because _Generic does not evaluate its control expression, the value of a is not modified.

Code Block
bgColor#FFcccc
langc
#include <stdio.h>

#define S(val) _Generic(val, int : 2, \
                             short : 3, \
                             default : 1)
void func(void) {
  int a = 0;
  int b = S(a++);
  printf("%d, %d\n", a, b);
}

Compliant Solution (_Generic)

In this compliant solution, a is incremented outside of the _Generic selection expression:

Code Block
bgColor#ccccFF
langc
#include <stdio.h>

#define S(val) _Generic(val, int : 2, \
                             short : 3, \
                             default : 1)
void func(void) {
  int a = 0;
  int b = S(a);
  ++a;
  printf("%d, %d\n", a, b);
} 

Noncompliant Code Example (_Alignof)

This noncompliant code example attempts to modify a variable while getting its default alignment value. The user may have expected val to be incremented as part of the _Alignof expression, but because _Alignof does not evaluate its operand, val is unchanged.

Code Block
bgColor#FFcccc
langc
#include <stdio.h>
 
void func(void) {
  int val = 0; 
  /* ... */ 
  size_t align = _Alignof(int[++val]);
  printf("%zu, %d\n", align, val);
  /* ... */
}

Compliant Solution (_Alignof)

 This compliant solution moves the expression out of the _Alignof operator:

Code Block
bgColor#ccccFF
langc
#include <stdio.h>
void func(void) {
  int val = 0; 
  /* ... */ 
  ++val;
  size_t align = _Alignof(int[val]);
  printf("%zu, %d\n", align, val);
  /* ... */
}

Exceptions

EXP44-C-EX1: Reading a volatile-qualified value is a side-effecting operation. However, accessing a value through a volatile-qualified type does not guarantee side effects will happen on the read of the value unless the underlying object is also volatile-qualified. Idiomatic reads of a volatile-qualified object are permissible as an operand to a sizeof()_Alignof(), or _Generic expression, as in the following example:

Code Block
bgColor#ccccFF
langc
void f(void) {
  int * volatile v;
  (void)sizeof(*v);
}

Risk Assessment

If expressions that appear to produce side effects are supplied to the sizeof operatoran operator that does not evaluate its operands, the returned result results may be different than expected. Depending on how this result is used, this it can lead to unintended program behavior.

Recommendation

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

EXP06

EXP44-C

low

Low

unlikely

Unlikely

low

Low

P3

L3

Automated Detection

Tool

Version

Checker

Description

Astrée
Include Page
Astrée_V
Astrée_V

alignof-side-effect
generic-selection-side-effect
sizeof

Fully checked
Axivion Bauhaus Suite

Include Page
Axivion Bauhaus Suite_V
Axivion Bauhaus Suite_V

CertC-EXP44
Clang
Include Page
Clang_V
Clang_V
-Wunevaluated-expressionCan diagnose some instance of this rule, but not all (such as the _Alignof NCCE).
CodeSonar
Include Page
CodeSonar_V
CodeSonar_V
LANG.STRUCT.SE.SIZEOF
LANG.STRUCT.SE.CGEN
Side effects in sizeof
Side Effects in C Generic Selection
Compass/ROSE

 

 




Coverity
Include Page
Coverity_V
Coverity_V

MISRA C 2004 Rule 12.3

Partially implemented
 

ECLAIR

Include Page
ECLAIR_V
ECLAIR_V

CC2.EXP06

Fully implemented

   
Helix QAC

Include Page
Helix QAC_V
Helix QAC_V

C3307
Klocwork
Include Page
Klocwork_V
Klocwork_V
MISRA.SIZEOF.SIDE_EFFECT
 

LDRA tool suite
Include Page
LDRA_V
LDRA_V

54 S, 653 S

Fully implemented

PRQA QA-C Include PagePRQA_VPRQA_V3307

Parasoft C/C++test
Include Page
Parasoft_V
Parasoft_V

CERT_C-EXP44-a
CERT_C-EXP44-b

Object designated by a volatile lvalue should not be accessed in the operand of the sizeof operator
The function call that causes the side effect shall not be the operand of the sizeof operator

PC-lint Plus

Include Page
PC-lint Plus_V
PC-lint Plus_V

9006

Partially supported: reports use of sizeof with an expression that would have side effects

Polyspace Bug Finder

Include Page
Polyspace Bug Finder_V
Polyspace Bug Finder_V

CERT C: Rule EXP44-C


Checks for situations when side effects of specified expressions are ignored (rule fully covered)

PVS-Studio

Include Page
PVS-Studio_V
PVS-Studio_V

V568
RuleChecker
Include Page
RuleChecker_V
RuleChecker_V

alignof-side-effect
generic-selection-side-effect
sizeof

Fully checked
Fully implemented

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

Related Guidelines

Key here (explains table format and definitions)

Taxonomy

Taxonomy item

Relationship

CERT C
++ Secure Coding Standard
EXP06
EXP52-CPP.
Operands to the sizeof operator should not contain
Do not rely on side effects

...

in unevaluated operandsPrior to 2018-01-12: CERT: Unspecified Relationship


...

Image Modified Image Modified Image Modified