Skip to content

Commit 276e5f3

Browse files
authored
Merge branch 'main' into codeql/upgrade-to-2.20.7
2 parents 1f4654e + 691460a commit 276e5f3

File tree

68 files changed

+827
-130
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+827
-130
lines changed

c/cert/src/qlpack.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: codeql/cert-c-coding-standards
2-
version: 2.48.0-dev
2+
version: 2.49.0-dev
33
description: CERT C 2016
44
suites: codeql-suites
55
license: MIT

c/cert/src/rules/ARR32-C/VariableLengthArraySizeNotInValidRange.ql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import cpp
2121
import codingstandards.c.cert
2222
import codingstandards.cpp.Overflow
23+
import semmle.code.cpp.dataflow.TaintTracking
2324

2425
/**
2526
* Gets the maximum size (in bytes) a variable-length array

c/cert/src/rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.ql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import codingstandards.c.cert
2020
import codingstandards.c.Errno
2121
import codingstandards.c.Signal
2222
import semmle.code.cpp.controlflow.Guards
23+
import semmle.code.cpp.dataflow.DataFlow
2324

2425
/**
2526
* A check on `signal` call return value

c/cert/src/rules/ERR33-C/DetectAndHandleStandardLibraryErrors.ql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import cpp
2020
import codingstandards.c.cert
2121
import semmle.code.cpp.commons.NULL
2222
import codingstandards.cpp.ReadErrorsAndEOF
23+
import semmle.code.cpp.dataflow.DataFlow
2324

2425
ComparisonOperation getAValidComparison(string spec) {
2526
spec = "=0" and result.(EqualityOperation).getAnOperand().getValue() = "0"
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# EXP16-C: Do not compare function pointers to constant values
2+
3+
This query implements the CERT-C rule EXP16-C:
4+
5+
> Do not compare function pointers to constant values
6+
7+
8+
## Description
9+
10+
Comparing a function pointer to a value that is not a null function pointer of the same type will be diagnosed because it typically indicates programmer error and can result in [unexpected behavior](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-unexpectedbehavior). Implicit comparisons will be diagnosed, as well.
11+
12+
## Noncompliant Code Example
13+
14+
In this noncompliant code example, the addresses of the POSIX functions `getuid` and `geteuid` are compared for equality to 0. Because no function address shall be null, the first subexpression will always evaluate to false (0), and the second subexpression always to true (nonzero). Consequently, the entire expression will always evaluate to true, leading to a potential security vulnerability.
15+
16+
```cpp
17+
/* First the options that are allowed only for root */
18+
if (getuid == 0 || geteuid != 0) {
19+
/* ... */
20+
}
21+
22+
```
23+
24+
## Noncompliant Code Example
25+
26+
In this noncompliant code example, the function pointers `getuid` and `geteuid` are compared to 0. This example is from an actual [vulnerability](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-vulnerability) ([VU\#837857](http://www.kb.cert.org/vuls/id/837857)) discovered in some versions of the X Window System server. The vulnerability exists because the programmer neglected to provide the open and close parentheses following the `geteuid()` function identifier. As a result, the `geteuid` token returns the address of the function, which is never equal to 0. Consequently, the `or` condition of this `if` statement is always true, and access is provided to the protected block for all users. Many compilers issue a warning noting such pointless expressions. Therefore, this coding error is normally detected by adherence to [MSC00-C. Compile cleanly at high warning levels](https://wiki.sei.cmu.edu/confluence/display/c/MSC00-C.+Compile+cleanly+at+high+warning+levels).
27+
28+
```cpp
29+
/* First the options that are allowed only for root */
30+
if (getuid() == 0 || geteuid != 0) {
31+
/* ... */
32+
}
33+
34+
```
35+
36+
## Compliant Solution
37+
38+
The solution is to provide the open and close parentheses following the `geteuid` token so that the function is properly invoked:
39+
40+
```cpp
41+
/* First the options that are allowed only for root */
42+
if (getuid() == 0 || geteuid() != 0) {
43+
/* ... */
44+
}
45+
46+
```
47+
48+
## Compliant Solution
49+
50+
A function pointer can be compared to a null function pointer of the same type:
51+
52+
```cpp
53+
/* First the options that are allowed only for root */
54+
if (getuid == (uid_t(*)(void))0 || geteuid != (uid_t(*)(void))0) {
55+
/* ... */
56+
}
57+
58+
```
59+
This code should not be diagnosed by an analyzer.
60+
61+
## Noncompliant Code Example
62+
63+
In this noncompliant code example, the function pointer `do_xyz` is implicitly compared unequal to 0:
64+
65+
```cpp
66+
int do_xyz(void);
67+
68+
int f(void) {
69+
/* ... */
70+
if (do_xyz) {
71+
return -1; /* Indicate failure */
72+
}
73+
/* ... */
74+
return 0;
75+
}
76+
77+
```
78+
79+
## Compliant Solution
80+
81+
In this compliant solution, the function `do_xyz()` is invoked and the return value is compared to 0:
82+
83+
```cpp
84+
int do_xyz(void);
85+
86+
int f(void) {
87+
/* ... */
88+
if (do_xyz()) {
89+
return -1; /* Indicate failure */
90+
}
91+
/* ... */
92+
return 0;
93+
}
94+
95+
```
96+
97+
## Risk Assessment
98+
99+
Errors of omission can result in unintended program flow.
100+
101+
<table> <tbody> <tr> <th> Recommendation </th> <th> Severity </th> <th> Likelihood </th> <th> Remediation Cost </th> <th> Priority </th> <th> Level </th> </tr> <tr> <td> EXP16-C </td> <td> Low </td> <td> Likely </td> <td> Medium </td> <td> <strong>P6</strong> </td> <td> <strong>L2</strong> </td> </tr> </tbody> </table>
102+
103+
104+
## Automated Detection
105+
106+
<table> <tbody> <tr> <th> Tool </th> <th> Version </th> <th> Checker </th> <th> Description </th> </tr> <tr> <td> <a> Astrée </a> </td> <td> 24.04 </td> <td> <strong>function-name-constant-comparison</strong> </td> <td> Partially checked </td> </tr> <tr> <td> <a> Coverity </a> </td> <td> 2017.07 </td> <td> <strong>BAD_COMPARE</strong> </td> <td> Can detect the specific instance where the address of a function is compared against 0, such as in the case of <code>geteuid</code> versus <code>getuid()</code> in the implementation-specific details </td> </tr> <tr> <td> <a> GCC </a> </td> <td> 4.3.5 </td> <td> </td> <td> Can detect violations of this recommendation when the <code>-Wall</code> flag is used </td> </tr> <tr> <td> <a> Helix QAC </a> </td> <td> 2024.4 </td> <td> <strong>C0428, C3004, C3344</strong> </td> <td> </td> </tr> <tr> <td> <a> Klocwork </a> </td> <td> 2024.4 </td> <td> <strong>CWARN.NULLCHECK.FUNCNAMECWARN.FUNCADDR</strong> </td> <td> </td> </tr> <tr> <td> <a> LDRA tool suite </a> </td> <td> 9.7.1 </td> <td> <strong>99 S</strong> </td> <td> Partially implemented </td> </tr> <tr> <td> <a> Parasoft C/C++test </a> </td> <td> 2024.2 </td> <td> <strong>CERT_C-EXP16-a</strong> </td> <td> Function address should not be compared to zero </td> </tr> <tr> <td> <a> PC-lint Plus </a> </td> <td> 1.4 </td> <td> <strong>2440, 2441</strong> </td> <td> Partially supported: reports address of function, array, or variable directly or indirectly compared to null </td> </tr> <tr> <td> <a> PVS-Studio </a> </td> <td> 7.35 </td> <td> <strong><a>V516</a>, <a>V1058</a></strong> </td> <td> </td> </tr> <tr> <td> <a> RuleChecker </a> </td> <td> 24.04 </td> <td> <strong>function-name-constant-comparison</strong> </td> <td> Partially checked </td> </tr> </tbody> </table>
107+
108+
109+
## Related Vulnerabilities
110+
111+
Search for [vulnerabilities](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-vulnerability) resulting from the violation of this rule on the [CERT website](https://www.kb.cert.org/vulnotes/bymetric?searchview&query=FIELD+KEYWORDS+contains+EXP16-C).
112+
113+
## Related Guidelines
114+
115+
<table> <tbody> <tr> <td> <a> SEI CERT C++ Coding Standard </a> </td> <td> <a> VOID EXP16-CPP. Avoid conversions using void pointers </a> </td> </tr> <tr> <td> <a> ISO/IEC TR 24772:2013 </a> </td> <td> Likely incorrect expressions \[KOA\] </td> </tr> <tr> <td> <a> ISO/IEC TS 17961 </a> </td> <td> Comparing function addresses to zero \[funcaddr\] </td> </tr> <tr> <td> <a> MITRE CWE </a> </td> <td> <a> CWE-480 </a> , Use of incorrect operator <a> CWE-482 </a> , Comparing instead of assigning </td> </tr> </tbody> </table>
116+
117+
118+
## Bibliography
119+
120+
<table> <tbody> <tr> <td> \[ <a> Hatton 1995 </a> \] </td> <td> Section 2.7.2, "Errors of Omission and Addition" </td> </tr> </tbody> </table>
121+
122+
123+
## Implementation notes
124+
125+
None
126+
127+
## References
128+
129+
* CERT-C: [EXP16-C: Do not compare function pointers to constant values](https://wiki.sei.cmu.edu/confluence/display/c)
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/**
2+
* @id c/cert/do-not-compare-function-pointers-to-constant-values
3+
* @name EXP16-C: Do not compare function pointers to constant values
4+
* @description Comparing function pointers to a constant value is not reliable and likely indicates
5+
* a programmer error.
6+
* @kind problem
7+
* @precision very-high
8+
* @problem.severity error
9+
* @tags external/cert/id/exp16-c
10+
* correctness
11+
* external/cert/severity/low
12+
* external/cert/likelihood/likely
13+
* external/cert/remediation-cost/medium
14+
* external/cert/priority/p6
15+
* external/cert/level/l2
16+
* external/cert/obligation/recommendation
17+
*/
18+
19+
import cpp
20+
import semmle.code.cpp.controlflow.IRGuards
21+
import codingstandards.c.cert
22+
import codingstandards.cpp.types.FunctionType
23+
import codingstandards.cpp.exprs.FunctionExprs
24+
import codingstandards.cpp.exprs.Guards
25+
26+
abstract class EffectivelyComparison extends Element {
27+
abstract string getExplanation();
28+
29+
abstract FunctionExpr getFunctionExpr();
30+
}
31+
32+
class ExplicitComparison extends EffectivelyComparison, ComparisonOperation {
33+
Expr constantExpr;
34+
FunctionExpr funcExpr;
35+
36+
ExplicitComparison() {
37+
funcExpr = getAnOperand() and
38+
constantExpr = getAnOperand() and
39+
exists(constantExpr.getValue()) and
40+
not funcExpr = constantExpr and
41+
not constantExpr.getExplicitlyConverted().getUnderlyingType() =
42+
funcExpr.getExplicitlyConverted().getUnderlyingType()
43+
}
44+
45+
override string getExplanation() { result = "$@ compared to constant value." }
46+
47+
override FunctionExpr getFunctionExpr() { result = funcExpr }
48+
}
49+
50+
class ImplicitComparison extends EffectivelyComparison, GuardCondition {
51+
ImplicitComparison() {
52+
this instanceof FunctionExpr and
53+
not getParent() instanceof ComparisonOperation
54+
}
55+
56+
override string getExplanation() { result = "$@ undergoes implicit constant comparison." }
57+
58+
override FunctionExpr getFunctionExpr() { result = this }
59+
}
60+
61+
from EffectivelyComparison comparison, FunctionExpr funcExpr, Element function, string funcName
62+
where
63+
not isExcluded(comparison,
64+
Expressions2Package::doNotCompareFunctionPointersToConstantValuesQuery()) and
65+
funcExpr = comparison.getFunctionExpr() and
66+
not exists(NullFunctionCallGuard nullGuard | nullGuard.getFunctionExpr() = funcExpr) and
67+
function = funcExpr.getFunction() and
68+
funcName = funcExpr.describe()
69+
select comparison, comparison.getExplanation(), function, funcName

c/cert/src/rules/FIO40-C/ResetStringsOnFgetsOrFgetwsFailure.ql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import cpp
2121
import codingstandards.cpp.FgetsErrorManagement
2222
import codingstandards.cpp.Dereferenced
2323
import codingstandards.c.cert
24+
import semmle.code.cpp.dataflow.DataFlow
2425

2526
/*
2627
* Models calls to `memcpy` `strcpy` `strncpy` and their wrappers

c/cert/src/rules/SIG30-C/CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,15 @@ class AsyncSafeVariableAccess extends VariableAccess {
3737
abstract class AsyncSafeFunction extends Function { }
3838

3939
/**
40-
* C standard library ayncronous-safe functions
40+
* C standard library asynchronous-safe functions
4141
*/
4242
class CAsyncSafeFunction extends AsyncSafeFunction {
4343
//tion, or the signal function with the first argument equal to the signal number corresponding to the signal that caused the invocation of the handler
4444
CAsyncSafeFunction() { this.hasGlobalName(["abort", "_Exit", "quick_exit", "signal"]) }
4545
}
4646

4747
/**
48-
* POSIX defined ayncronous-safe functions
48+
* POSIX defined asynchronous-safe functions
4949
*/
5050
class PosixAsyncSafeFunction extends AsyncSafeFunction {
5151
PosixAsyncSafeFunction() {
@@ -73,7 +73,7 @@ class PosixAsyncSafeFunction extends AsyncSafeFunction {
7373
}
7474

7575
/**
76-
* Application defined ayncronous-safe functions
76+
* Application defined asynchronous-safe functions
7777
*/
7878
class ApplicationAsyncSafeFunction extends AsyncSafeFunction {
7979
pragma[nomagic]
@@ -122,5 +122,5 @@ where
122122
or
123123
fc instanceof AsyncUnsafeRaiseCall
124124
)
125-
select fc, "Asyncronous-unsafe function calls within a $@ can lead to undefined behavior.",
125+
select fc, "Asynchronous-unsafe function calls within a $@ can lead to undefined behavior.",
126126
handler.getRegistration(), "signal handler"

c/cert/test/qlpack.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: codeql/cert-c-coding-standards-tests
2-
version: 2.48.0-dev
2+
version: 2.49.0-dev
33
extractor: cpp
44
license: MIT
55
dependencies:

c/cert/test/rules/ARR32-C/VariableLengthArraySizeNotInValidRange.expected

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
WARNING: module 'DataFlow' has been deprecated and may be removed in future (VariableLengthArraySizeNotInValidRange.ql:109,11-19)
2-
WARNING: module 'TaintTracking' has been deprecated and may be removed in future (VariableLengthArraySizeNotInValidRange.ql:92,5-18)
1+
WARNING: module 'DataFlow' has been deprecated and may be removed in future (VariableLengthArraySizeNotInValidRange.ql:110,11-19)
2+
WARNING: module 'TaintTracking' has been deprecated and may be removed in future (VariableLengthArraySizeNotInValidRange.ql:93,5-18)
33
| test.c:14:8:14:8 | VLA declaration | Variable-length array dimension size may be in an invalid range. |
44
| test.c:15:8:15:8 | VLA declaration | Variable-length array dimension size may be in an invalid range. |
55
| test.c:16:8:16:8 | VLA declaration | Variable-length array dimension size may be in an invalid range. |

0 commit comments

Comments
 (0)