Skip to content

Commit aeae208

Browse files
authored
Merge pull request #15456 from MathiasVP/fix-scanf-fp
C++: Fix FP in `cpp/incorrectly-checked-scanf`
2 parents 391ca5d + 044d94c commit aeae208

File tree

4 files changed

+44
-0
lines changed

4 files changed

+44
-0
lines changed

cpp/ql/src/Critical/ScanfChecks.qll

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,37 @@ private predicate isLinuxKernel() {
2020
exists(Macro macro | macro.getName() in ["_LINUX_KERNEL_SPRINTF_H_", "_LINUX_KERNEL_H"])
2121
}
2222

23+
/**
24+
* Gets the value of the EOF macro.
25+
*
26+
* This is typically `"-1"`, but this is not guaranteed to be the case on all
27+
* systems.
28+
*/
29+
private string getEofValue() {
30+
exists(MacroInvocation mi |
31+
mi.getMacroName() = "EOF" and
32+
result = unique( | | mi.getExpr().getValue())
33+
)
34+
}
35+
36+
/**
37+
* Holds if the value of `call` has been checked to not equal `EOF`.
38+
*/
39+
private predicate checkedForEof(ScanfFunctionCall call) {
40+
exists(IRGuardCondition gc |
41+
exists(Instruction i, ConstantInstruction eof |
42+
eof.getValue() = getEofValue() and
43+
i.getUnconvertedResultExpression() = call and
44+
gc.comparesEq(valueNumber(i).getAUse(), eof.getAUse(), 0, _, _)
45+
)
46+
)
47+
}
48+
2349
/**
2450
* Holds if `call` is a `scanf`-like call were the result is only checked against 0, but it can also return EOF.
2551
*/
2652
predicate incorrectlyCheckedScanf(ScanfFunctionCall call) {
2753
exprInBooleanContext(call) and
54+
not checkedForEof(call) and
2855
not isLinuxKernel() // scanf in the linux kernel can't return EOF
2956
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* The "Incorrect return-value check for a 'scanf'-like function" query (`cpp/incorrectly-checked-scanf`) no longer reports an alert when an explicit check for EOF is added.

cpp/ql/test/query-tests/Critical/MissingCheckScanf/MissingCheckScanf.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@
1414
| test.cpp:404:25:404:25 | u | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:403:6:403:11 | call to sscanf | call to sscanf |
1515
| test.cpp:416:7:416:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:413:7:413:11 | call to scanf | call to scanf |
1616
| test.cpp:423:7:423:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:420:7:420:11 | call to scanf | call to scanf |
17+
| test.cpp:460:6:460:10 | value | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:455:12:455:17 | call to sscanf | call to sscanf |

cpp/ql/test/query-tests/Critical/MissingCheckScanf/test.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,4 +446,16 @@ void bad_check() {
446446
}
447447
use(i); // GOOD [FALSE POSITIVE]: Technically no security issue, but code is incorrect.
448448
}
449+
}
450+
451+
#define EOF (-1)
452+
453+
void disjunct_boolean_condition(const char* modifier_data) {
454+
long value;
455+
auto rc = sscanf(modifier_data, "%lx", &value);
456+
457+
if((rc == EOF) || (rc == 0)) {
458+
return;
459+
}
460+
use(value); // GOOD
449461
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy