Main Content

CERT C: Rec. MSC23-C

R2026b

Beware of vendor-specific library and language differences

Since R2026b

Description

Beware of vendor-specific library and language differences1

Polyspace Implementation

Polyspace® checks for these issues:

  • Use of Nonstandard C syntax

  • Use of Language Extensions

  • Missing Binary Mode in fopen

Examples

expand all

Issue

This issue is reported in the coding patterns described in the following table. Note that:

Coding PatternC Standard DependenceAdditional Information
A signed integer constant falls outside the range of long int, or an unsigned integer constant falls outside the range of unsigned long int.Checked for C90 only.The rule checker uses your specifications for the size of a long int variable, typically 32 bits. See also Target processor type (-target).
An array of size zero is used.Checked for C90 only. 
The number of macros defined in a translation unit exceeds the limit specified in the standard.

Number of macro definitions allowed:

  • C90: 1024

  • C99 and later: 4095

A translation unit consists of a source file and headers included directly or indirectly in the source file. These are the files necessary to create the smallest object file during compilation. The rule checker requires that the number of macros in a source plus included headers must not exceed the limit specified in the standard.

The depth of nesting in control flow statements such as if and while exceeds the limit specified in the standard.

Maximum nesting depth allowed:

  • C90: 15

  • C99 and later: 127

 
The number of levels of inclusion using include files exceeds the limit specified in the standard.

Maximum number of levels of inclusion allowed:

  • C90: 8

  • C99 and later: 15

 
The number of members of a structure or union exceeds the limit specified in the standard.

Maximum number of members in a structure or union:

  • C90: 127

  • C99 and later: 1023

 
The number of levels of nesting in a structure exceeds the limit specified in the standard.

Maximum depth of nesting:

  • C90: 15

  • C99 and later: 63

 
The number of constants in a single enumeration exceeds the limit specified in the standard.

Maximum number of enumeration constants allowed:

  • C90: 127

  • C99 and later: 1023

 
An assembly language statement is used.Checked for all C standards. 
A nonstandard preprocessor directive is used.Checked for all C standards.The rule checker flags uses of preprocessor directives that are not found in the C standard, for instance, #ident, #alias, and #assert.
Unrecognized text follows a preprocessor directive.Checked for all C standards.

The rule checker flags extraneous text following a preprocessor directive, that is, a line beginning with #. For instance:

#include <header> code

Unnamed unions or empty structs are used.Checked for C90. 
An enum contains a trailing comma.Checked for C90. 

Standard compilation error messages do not lead to a violation of this MISRA™ rule.

Risk

Nonstandard C syntax is not guaranteed to be accepted or interpreted the same way by all compilers. Code that compiles and runs correctly on one toolchain might be rejected, silently ignored, or produce different behavior on another. If you are unaware of these dependencies, porting the code to a different platform can introduce unexpected failures.

Fix

Identify and document the vendor-specific dependency. If portability is required, replace the nonstandard construct with a standard-conforming alternative or isolate it behind a platform-specific guard.

Example — Nonstandard Preprocessor Directive

In this example, Polyspace reports a violation on the nonstandard #unknownDirective preprocessor directive.


#include <stdio.h>

#unknownDirective "Hello World"  // Noncompliant

void print_message(void) {
    printf("Hello World\n");
}
Correction — Remove Nonstandard Directive

Remove the nonstandard directive. Use standard C constructs to achieve the same purpose.


#include <stdio.h>

/* Removed nonstandard directive */  // Compliant

void print_message(void) {
    printf("Hello World\n");
}
Issue

The issue occurs when code uses a language extension not specified by the C standard. The specific extensions flagged depend on the C standard version used in the analysis. Extensions include:

  • C90:

    • long long int type including constants

    • long double type

    • inline keyword

    • _Bool keyword

    • Hexadecimal floating-point constants

    • Designated initializers

    • Local label declarations

    • typeof operator

    • Casts to union

    • Compound literals

    • Mixed declarations and code, in other words, declarations appearing in a block after executable statements instead of the beginning of the block

    • Statements and declarations in expressions

    • __func__ predefined identifier

    • _Pragma preprocessing operator

    • Macros with variable arguments list

    • asm functions

    • Anonymous unions

    • Empty struct

  • C99:

    • short long int type

    • Local label declarations

    • typeof operator

    • Casts to union

    • Statements and declarations in expressions

    • asm functions

    • Anonymous unions

    • Empty struct

Risk

Language extensions are not part of the C standard and their behavior varies across compilers. Code that uses them is tied to a specific toolchain. When ported, the extension might not exist, might have different semantics, or might silently produce incorrect results.

Fix

Identify and document the vendor-specific dependency. If portability is required, replace the language extension with a standard-conforming alternative or isolate it behind a platform-specific guard.

Example — Cast to Union Type

In this example, Polyspace reports a violation because a value is cast to a union type, which is a compiler extension not specified by the C standard.


union numeric { int i; double d; };

void convert_value(void) {
    int x = 42;
    union numeric result;
    result = (union numeric) x;  // Noncompliant
}
Correction —Assign to Union Member

Assign the value directly to the intended union member instead of using a cast-to-union expression.


union numeric { int i; double d; };

void convert_value(void) {
    int x = 42;
    union numeric result;
    result.i = x;  // Compliant
}
Issue

The issue occurs when fopen is called with a text mode parameter that does not include the "b" flag for binary translation mode.

Risk

When fopen opens a file in text mode without using the binary translation mode, the C library performs newline translation whose behavior is defined by the platform. For instance, on Windows the library translates \r\n to \n on read and \n to \r\n on write, while on POSIX systems no translation occurs. Because this translation is vendor-specific, different byte sequence is read or written depending on the platform.

Fix

Open the file in binary mode by appending "b" to the mode string. For example, use "rb" instead of "r". If text mode newline translation is intentionally required, document the platform dependency.

Example —File Opened Without Binary Mode

In this example, Polyspace reports a violation because fopen uses text mode "r" without the binary flag.


#include <stdio.h>

void read_file(void) {
    FILE *fp = fopen("data.txt", "r");  // Noncompliant
    if (fp) {
        int count = 0;
        while (!feof(fp) && !ferror(fp)) {
            ++count;
            (void)fgetc(fp);
        }
        fclose(fp);
    }
}
Correction —Open File in Binary Mode

Add the "b" flag to the mode string to open the file in binary mode.


#include <stdio.h>

void read_file(void) {
    FILE *fp = fopen("data.txt", "rb");  // Compliant
    if (fp) {
        int count = 0;
        while (!feof(fp) && !ferror(fp)) {
            ++count;
            (void)fgetc(fp);
        }
        fclose(fp);
    }
}

Check Information

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

Version History

Introduced in R2026b

expand all


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.