Main Content

CERT C: Rec. MSC06-C

Beware of compiler optimizations

Since R2026a

Description

Beware of compiler optimizations.1

Polyspace Implementation

The rule checker checks for these issues:

  • Compiler optimization removes uncertain memory clearing

  • Compiler optimization removes empty while-loop

Examples

expand all

Issue

This issue occurs when code contains memory clearing operations that may be removed or altered by compiler optimizations. For example, memset() or bzero() calls that clears sensitive data may be optimized away if the memory is not accessed afterward.

Risk

Failure to adhere to this rule can result in unexpected and unwanted compiler optimizations that alter program behavior in critical ways. For example, if a buffer that stores sensitive data is cleared using memset() but the memory is not accessed afterward, the compiler may optimize away the clearing operation and leave sensitive data in memory.

Fix

Solutions include:

  • When clearing sensitive data, access the memory after the clearing operation, or use functions or compiler-specific attributes that guarantee the memory is actually cleared.

  • Review compiler documentation and options to understand how optimizations may affect your code and use appropriate pragmas or volatile qualifiers.

Example — Compiler removes function calls that clears sensitive data

In this example, after using the buffer pwd to store a password, the programmer attempts to clear its contents using memset(). However, since pwd is not accessed after the call to memset(), some compiler optimization modes may determine that clearing the buffer has no observable effect and remove the memset() call. As a result, the sensitive password data may remain in memory, posing a security risk.

#include <string.h>

int GetPassword(char*, int);

void getPassword_NonCompliant_memset(void) {
    char pwd[64];

    if (GetPassword(pwd, sizeof(pwd))) {
    }

    memset(pwd, 0, sizeof(pwd));   // Noncompliant
}
void foo() {
	char pwd[64];
	bzero(pwd, sizeof(pwd)); //Noncompliant

}
Correction — Touch memory after memset() function

Touch the memory after the call to memset() or bzero(). This technique prevents some compilers from optimizing out these calls, but does not work for all implementations.

#include <string.h>

int GetPassword(char*, int);

void getPassword_Compliant_memset(void)
{
    char pwd[64];

    if (GetPassword(pwd, sizeof(pwd))) {
    }

    memset(pwd, 0, sizeof(pwd));    // Compliant
    volatile char *vp = pwd;
    *vp = *vp;
}

void foo() {
	char pwd[64];
	bzero(pwd, sizeof(pwd)); //Compliant
       volatile char *vp = pwd;
       *vp = *vp; 
}

Another solution is to use a memory clearing function that is not optimized away by the compiler. Refer to your compiler documentation for secure memory clearing functions (for example, explicit_bzero() or SecureZeroMemory() on Windows), or use platform- or compiler-specific pragmas or attributes.

Issue

This issue occurs when infinite while-loops controlled by nonconstant expressions can be optimized out by the compiler, potentially changing program behavior. For example, you can use an empty infinite while-loop to implement a sleep function capability on platforms that do not support sleep() or equivalent functions.

Risk

Infinite loops may be optimized away by the compiler if their controlling expressions are not constant, potentially causing the program to exit or behave unpredictably. Such optimizations can compromise security, reliability, and correctness, particularly when handling sensitive information or implementing essential control flow constructs.

Fix

Solutions include:

  • Use constant expressions (such as 1 or true) to control infinite while-loops and prevent the compiler from removing them.

  • Review compiler documentation and options to understand how optimizations may affect your code and use appropriate pragmas or volatile qualifiers.

Example — Compiler Removes while-Loop Controlled by Nonconstant Variable

In this example, the while-loop is controlled by a nonconstant variable always. The compiler may determine that the value of always does not change and, under certain optimization settings, remove the loop. This can cause the program to terminate unexpectedly or behave differently than intended.

static int always = 1;

int main_example(void)
{
    while (always) {              // Noncompliant
    }
}
Correction — Replace Nonconstant Variable with Constant Expression

Change the while-loop to use a constant expression 1 as the controlling expression. This allows the compiler to recognize the while-loop as infinite and to not optimize it away.

int main_example(void)
{
    while (1) {                   // Compliant
    }
}

Check Information

Group: Rec. 48. Miscellaneous (MSC)
PQL Name: std.cert.MSC06_C

Version History

Introduced in R2026a


1 This software has been created by MathWorks incorporating portions of: the “SEI CERT-C Website,” © 2017 Carnegie Mellon University, the SEI CERT-C++ Web site © 2017 Carnegie Mellon University, ”SEI CERT C Coding Standard – Rules for Developing safe, Reliable and Secure systems – 2016 Edition,” © 2016 Carnegie Mellon University, and “SEI CERT C++ Coding Standard – Rules for Developing safe, Reliable and Secure systems in C++ – 2016 Edition” © 2016 Carnegie Mellon University, with special permission from its Software Engineering Institute.

ANY MATERIAL OF CARNEGIE MELLON UNIVERSITY AND/OR ITS SOFTWARE ENGINEERING INSTITUTE CONTAINED HEREIN IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.

This software and associated documentation has not been reviewed nor is it endorsed by Carnegie Mellon University or its Software Engineering Institute.