Versions Compared

Key

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

Platform dependencies may be introduced to improve performance on a particular platform. This can be a dangerous practice, particularly if these dependencies are not appropriately documented during development and addressed during porting. Platform dependencies that have no performance or other benefits should consequently be avoided because they may introduce errors during porting.

The C99 standard C Standard identifies two four different kinds of non-portable behavior, implementation-defined and unspecified.

C99 Section 3.4.1 defines implementation-defined behavior as

nonportable behavior. Each section of Annex J of the C Standard enumerates distinct instances of behaviors of each kind.

Nonportable Behavior

Definition

Annex J Section

Unspecified behavior

Behavior for which the standard provides two or more possibilities and imposes no further requirements on which is chosen in any instance.

J.1

Undefined behavior

Behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which the standard imposes no requirements. An example of undefined behavior is the behavior on signed integer overflow.

J.2

Implementation-defined behavior

Unspecified behavior whereby

...

each implementation documents how the choice is made

...

An example of implementation-defined behavior is the propagation of the high-order bit when a signed integer is shifted right.

C99 Section 3.4.4 defines unspecified behavior as

...

.

J.3

Locale-specific behavior

Behavior that depends on local conventions of nationality, culture, and language that each implementation documents.

J.4

An example of undefined behavior is passing a null char* pointer as an argument to the printf function corresponding to the %s format specification. Although some implementations (such as the GNU C Library) provide well-defined semantics for this case, others do not, causing programs that rely on this behavior to fail abnormally.

An example of unspecified behavior is the order in which the arguments to a function are evaluated.

Appendix J.1, "Unspecified behavior," provides a list of unspecified behaviors in C99, and Appendix J.3, "Implementation-defined behavior," provides a list of implementation-defined behaviors in C99An example of implementation-defined behavior is the propagation of the high-order bit when a signed integer is shifted right.

Most legitimate platform dependencies can and should be isolated in separate modules that use expose portable, platform-agnostic interfaces but to platform-specific implementations. Portable applications that cannot avoid relying on platform-specific details should always provide a generic, portable, standards-based solution as a fallback mechanism for the platform-specific alternative. That way, such an application can be more easily ported to new platforms without an excessive risk of security flaws caused by assumptions that do not hold in the new environment.

Noncompliant Code Example

This noncompliant code example uses the complement operator in the test for unsigned integer overflow. It assumes both numbers are nonnegative:

Code Block
bgColor#FFCCCC
langc

unsignedsigned int si;
signed int ui1, ui2,si2;
signed int sum;

if (~ui1si < 0 || si2 < 0) {
  /* Handle error condition */
}
if (~si < ui2si2) {
  /* handleHandle error condition */
}
sum = ui1si + ui2si2;

This code assumes that the implementation uses two's complement representation. This assumption is commonly true , but is not guaranteed by the standard.

...

This compliant solution implements a strictly conforming test for unsigned overflow.:

Code Block
bgColor#ccccff
langc
unsigned int si;
unsigned int ui1, ui2,si2;
unsigned int sum;

if (si < 0 || si2 < 0) {
  /* Handle error condition */
}
if (UINTINT_MAX - ui1si < ui2si2) {
  /* handleHandle error condition */
}
sum = ui1si + ui2si2;

If the noncompliant form of this test is truly faster, talk to your compiler vendor because, because if these tests are equivalent, optimization should occur. If both forms have the same performance, prefer the portable form.

Anchor
ncce_strerror_r
ncce_strerror_r

Noncompliant Code Example (strerror_r)

The GNU libc implementation of strerror_r declares the function to return char*, in conflict with the POSIX specification. This noncompliant code example relies on this return type to pass the return value as an argument to the %s formatting directive to fprintf. The behavior of the example will be undefined on a platform that declares the return type of strerror_r() to be int, in accordance with POSIX.

Code Block
bgColor#FFCCCC
langc
void f() {
  char buf[BUFSIZ];
  fprintf(stderr, "Error: %s\n",
          strerror_r(errno, buf, sizeof buf));
}

Anchor
cs_strerror_r
cs_strerror_r

Compliant Solution (strerror_r)

The compliant solution disables the nonconforming declaration of strerror_r() by explicitly requesting POSIX conformance before including the <string.h> header that declares the function and handles the function's failure by copying the "Unknown error" string into the buffer. An alternate solution is to use the strerror_s() function defined by Annex K.

Note that the function assigns the result of the call to strerror_r() to a variable of type int. This assignment is a defense-in-depth strategy guarding against inadvertently invoking strerror_r() that returns char*: a conforming compiler is required to issue a diagnostic for the ill-formed conversion from char* to int.

Code Block
bgColor#CCCCFF
langc
#define _XOPEN_SOURCE 600
#include <string.h>
#include <stdio.h>
#include <errno.h>
void f() {
  char buf[BUFSIZ];
  int result;

  result = strerror_r(errno, buf, sizeof buf);

  if (0 != result) {
    strcpy(buf, "Unknown error");
  }
  fprintf(stderr, "Error: %s\n", buf);
}

Risk Assessment

Unnecessary platform dependencies are, by definition, unnecessary. Avoiding these dependencies can eliminate porting errors resulting from invalidated assumptions.

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

MSC14-C

low

Low

unlikely

Unlikely

medium

Medium

P2

L3

Automated Detection

Tool

Version

Checker

Description

Helix QAC

Include Page
Helix QAC_V
Helix QAC_V

C0202, C0240, C0241, C0242, C0243, C0246, C0284, C0551, C0581, C0601, C0633, C0634, C0635, C0660, C0662, C0830, C0831, C0840, C0899, C1001, C1002, C1003, C1006, C1008, C1012, C1014, C1015, C1019, C1020, C1021, C1022, C1026, C1028, C1029, C1034, C1035, C1036, C1037, C1038, C1041, C1042, C1043, C1044, C1045, C1046, C1434, C3664


LDRA tool suite
Include Page
LDRA_V
LDRA_V
17 D, 69 S, 42 SPartially implemented
Parasoft C/C++test
Include Page
Parasoft_V
Parasoft_V
CERT_C-MSC14-a

Evaluation of constant unsigned integer expressions should not lead to wrap-around

Related Vulnerabilities

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

References

Wiki Markup
\[[Dowd 06|AA. C References#Dowd 06]\] Chapter 6, "C Language Issues" (Arithmetic Boundary Conditions, pp. 211-223)
\[[ISO/IEC 9899:1999|AA. C References#ISO/IEC 9899-1999]\] Section 3.4.1, "implementation-defined behavior," Section 3.4.4, "unspecified behavior," Appendix J.1, "Unspecified behavior," and Appendix J.3, "Implementation-defined behavior"
\[[ISO/IEC PDTR 24772|AA. C References#ISO/IEC PDTR 24772]\] "BQF Unspecified Behaviour"
\[[Seacord 05a|AA. C References#Seacord 05]\] Chapter 5, "Integers"

Related Guidelines

Bibliography

[Dowd 2006]Chapter 6, "C Language Issues" ("Arithmetic Boundary Conditions," pp. 211–223)
[Seacord 2013]Chapter 5, "Integer Security"


...

Image Added Image Added Image Removed      13. Miscellaneous (MSC)       Image Modified