Two consecutive question marks signify the start of a trigraph sequence.
According to the C99 Standard [[ISO/IEC 9899-1999]]:
All occurrences in a source file of the following sequences of three characters (that is, trigraph sequences) are replaced with the corresponding single character.
??=
#
??)
]
??!
|
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="4b3c7bc6-13c6-4483-ad8e-a93eb7ff893b"><ac:plain-text-body><![CDATA[
??(
[
??'
^
??>
}
]]></ac:plain-text-body></ac:structured-macro>
??/
\
??<
{
??-
~
Non-Compliant Code Example
In this non-compliant code example, a++
is not executed, because the trigraph sequence ??/
is replaced by \,
logically putting a++
on the same line as the comment.
// what is the value of a now??/ a++;
Compliant Solution
The following compliant solution eliminates the accidental introduction of the trigraph by separating the ?'s
// what is the value of a now? ?/ a++;
Non-Compliant Code Example
This non-compliant code example includes the trigraph sequence ??!
, which is replaced by the character |
.
size_t i; /* assignment of i */ if (i > 9000) { puts("Over 9000!??!"); }
This example prints Over 9000!|
if a C99-compliant compiler is used.
Compliant Solution
The compliant solution uses string concatenation to concatenate the two question marks; otherwise they are interpreted as beginning a trigraph sequence.
size_t i; /* assignment of i */ if (i > 9000) { puts("Over 9000!?""?!"); }
The above code prints Over 9000!??!
, as intended.
Risk Assessment
Inadvertent trigraphs can result in unexpected behavior. Some compilers provide options to warn when trigraphs are encountered, or to disable trigraph expansion. Use the warning options and ensure your code compiles cleanly (see MSC00-A. Compile cleanly at high warning levels).
Recommendation |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
PRE07-A |
1 (low) |
1 (unlikely) |
2 (medium) |
P2 |
L3 |
Automated Detection
GCC provides a --no-trigraph
option that is enabled by default. GCC also provides the -Wtrigraphs
option that warns when trigraphs are used.
The LDRA tool suite V 7.6.0 is able to detect violations of this recommendation.
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
[[ISO/IEC 9899-1999]] Section 5.2.1.1, "Trigraph sequences"
[[MISRA 04]] Rule 4.2
[Wikipedia] "C Trigraphs"
PRE06-A. Enclose header file in an inclusion guard 01. Preprocessor (PRE) PRE08-A. Guarantee that header filenames are unique