Two consecutive question marks signify the start of a trigraph sequence. According to the C99 Standard \[C Standard, subclause 5.2.1.1 [ISO/IEC 9899-1999|AA. C References#ISO/IEC 9899-1999]\]:9899:2011],Wiki Markup
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="0d0c34d4-3f2f-4137-a96a-507a44eb55a3"><ac:plain-text-body><![CDATA[
]]></ac:plain-text-body></ac:structured-macro>
??(
[
??'
^
??>
}
??/
\
??<
{
??-
~
...
Noncompliant Code Example
In this non-compliant noncompliant code example, a++ is not executed , because the trigraph sequence ??/ is replaced by \, logically putting a++ on the same line as the comment.:
| Code Block | ||||
|---|---|---|---|---|
| ||||
// whatWhat is the value of a now??/ a++; |
Compliant Solution
The following This compliant solution eliminates the accidental introduction of the trigraph by separating the ?'squestion marks:
| Code Block | ||||
|---|---|---|---|---|
| ||||
// whatWhat is the value of a now? ?/ a++; |
...
Noncompliant Code Example
This non-compliant noncompliant code example includes the trigraph sequence ??!, which is replaced by the character |.:
| Code Block | ||||
|---|---|---|---|---|
| ||||
size_t i; = /* assignmentSome ofinitial ivalue */; if (i > 9000) { if (puts("Over 9000!??!");) == EOF) { /* Handle error */ } } |
This example prints Over 9000!| if a C99C-compliant compiler is used.
Compliant Solution
The This compliant solution uses string concatenation to concatenate the two question marks; otherwise, they are interpreted as beginning a trigraph sequence.:
| Code Block | ||||
|---|---|---|---|---|
| ||||
size_t i = /* Some initial value */; /* assignmentAssignment of i */ if (i > 9000) { if (puts("Over 9000!?""?!");) == EOF) { /* Handle error */ } } |
The above code This code prints Over 9000!??!, as intended.
Risk Assessment
Inadvertent trigraphs can lead to 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 See MSC00-AC. Compile cleanly at high warning levels.).
Recommendation | Severity | Likelihood | Detectable |
|---|
Repairable | Priority | Level |
|---|---|---|
PRE07- |
1 (low)
1 (unlikely)
C | Low | Unlikely | Yes | No | P2 | L3 |
Automated Detection
...
| Tool | Version | Checker | Description | ||||||
|---|---|---|---|---|---|---|---|---|---|
| Astrée |
| trigraph | Fully checked | ||||||
| Axivion Bauhaus Suite |
| CertC-PRE07 | |||||||
| CC2.PRE07 | Fully implemented | |||||||
| GCC |
| Can detect violation of this recommendation when the | |||||||
| Helix QAC |
| C3601 | |||||||
| LDRA tool suite |
| 81 S | Fully implemented | ||||||
| Parasoft C/C++test |
| CERT_C-PRE07-a | Trigraphs shall not be used | ||||||
| PC-lint Plus |
| 584, 854, 9060 | Fully supported | ||||||
| Polyspace Bug Finder |
| CERT C: Rec. PRE07-C | Checks for use of trigraphs (rec. fully covered) | ||||||
| RuleChecker |
| trigraph | Fully checked | ||||||
| SonarQube C/C++ Plugin |
| TrigraphUsage |
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
...
Related Guidelines
| SEI CERT C++ Coding Standard | VOID PRE07-CPP. Avoid using repeated question marks |
| MISRA C:2012 | Rule 4.2 (advisory) |
Bibliography
| [ISO/IEC 9899:2011] | Subclause 5.2.1.1, "Trigraph Sequences" |
...
"Trigraph sequences" \[[MISRA 04|AA. C References#MISRA 04]\] Rule 4.2 \[Wikipedia\] ["C Trigraphs"|http://en.wikipedia.org/wiki/C_trigraph]PRE06-A. Enclose header file in an inclusion guard 01. Preprocessor (PRE) PRE08-A. Guarantee that header filenames are unique