Skip to content

Commit e4e472e

Browse files
author
Dave Bartolomeo
authored
Merge pull request github#14512 from MathiasVP/fix-size-in-invalid-ptr-deref
C++: Fix size deduction in `cpp/invalid-pointer-deref`
2 parents 25c416e + d8a049f commit e4e472e

File tree

3 files changed

+39
-3
lines changed

3 files changed

+39
-3
lines changed

cpp/ql/lib/semmle/code/cpp/security/InvalidPointerDereference/AllocationToInvalidPointer.qll

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,17 +60,31 @@ private import semmle.code.cpp.rangeanalysis.new.RangeAnalysisUtil
6060

6161
private VariableAccess getAVariableAccess(Expr e) { e.getAChild*() = result }
6262

63+
/**
64+
* Gets a (sub)expression that may be the result of evaluating `size`.
65+
*
66+
* For example, `getASizeCandidate(a ? b : c)` gives `a ? b : c`, `b` and `c`.
67+
*/
68+
bindingset[size]
69+
pragma[inline_late]
70+
private Expr getASizeCandidate(Expr size) {
71+
result = size
72+
or
73+
result = [size.(ConditionalExpr).getThen(), size.(ConditionalExpr).getElse()]
74+
}
75+
6376
/**
6477
* Holds if the `(n, state)` pair represents the source of flow for the size
6578
* expression associated with `alloc`.
6679
*/
6780
predicate hasSize(HeuristicAllocationExpr alloc, DataFlow::Node n, int state) {
68-
exists(VariableAccess va, Expr size, int delta |
81+
exists(VariableAccess va, Expr size, int delta, Expr s |
6982
size = alloc.getSizeExpr() and
83+
s = getASizeCandidate(size) and
7084
// Get the unique variable in a size expression like `x` in `malloc(x + 1)`.
71-
va = unique( | | getAVariableAccess(size)) and
85+
va = unique( | | getAVariableAccess(s)) and
7286
// Compute `delta` as the constant difference between `x` and `x + 1`.
73-
bounded1(any(Instruction instr | instr.getUnconvertedResultExpression() = size),
87+
bounded1(any(Instruction instr | instr.getUnconvertedResultExpression() = s),
7488
any(LoadInstruction load | load.getUnconvertedResultExpression() = va), delta) and
7589
n.asExpr() = va and
7690
state = delta

cpp/ql/test/query-tests/Security/CWE/CWE-193/InvalidPointerDeref.expected

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,12 @@ edges
181181
| test.cpp:833:37:833:39 | end | test.cpp:815:52:815:54 | end |
182182
| test.cpp:841:18:841:35 | call to malloc | test.cpp:842:3:842:20 | ... = ... |
183183
| test.cpp:848:20:848:37 | call to malloc | test.cpp:849:5:849:22 | ... = ... |
184+
| test.cpp:856:12:856:35 | call to malloc | test.cpp:857:16:857:29 | ... + ... |
185+
| test.cpp:856:12:856:35 | call to malloc | test.cpp:857:16:857:29 | ... + ... |
186+
| test.cpp:856:12:856:35 | call to malloc | test.cpp:860:5:860:11 | ... = ... |
187+
| test.cpp:857:16:857:29 | ... + ... | test.cpp:857:16:857:29 | ... + ... |
188+
| test.cpp:857:16:857:29 | ... + ... | test.cpp:860:5:860:11 | ... = ... |
189+
| test.cpp:857:16:857:29 | ... + ... | test.cpp:860:5:860:11 | ... = ... |
184190
nodes
185191
| test.cpp:4:15:4:33 | call to malloc | semmle.label | call to malloc |
186192
| test.cpp:5:15:5:22 | ... + ... | semmle.label | ... + ... |
@@ -307,6 +313,10 @@ nodes
307313
| test.cpp:842:3:842:20 | ... = ... | semmle.label | ... = ... |
308314
| test.cpp:848:20:848:37 | call to malloc | semmle.label | call to malloc |
309315
| test.cpp:849:5:849:22 | ... = ... | semmle.label | ... = ... |
316+
| test.cpp:856:12:856:35 | call to malloc | semmle.label | call to malloc |
317+
| test.cpp:857:16:857:29 | ... + ... | semmle.label | ... + ... |
318+
| test.cpp:857:16:857:29 | ... + ... | semmle.label | ... + ... |
319+
| test.cpp:860:5:860:11 | ... = ... | semmle.label | ... = ... |
310320
subpaths
311321
#select
312322
| test.cpp:6:14:6:15 | * ... | test.cpp:4:15:4:33 | call to malloc | test.cpp:6:14:6:15 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:4:15:4:33 | call to malloc | call to malloc | test.cpp:5:19:5:22 | size | size |
@@ -344,3 +354,4 @@ subpaths
344354
| test.cpp:821:7:821:12 | ... = ... | test.cpp:793:14:793:32 | call to malloc | test.cpp:821:7:821:12 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:793:14:793:32 | call to malloc | call to malloc | test.cpp:794:21:794:24 | size | size |
345355
| test.cpp:842:3:842:20 | ... = ... | test.cpp:841:18:841:35 | call to malloc | test.cpp:842:3:842:20 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:841:18:841:35 | call to malloc | call to malloc | test.cpp:842:11:842:15 | index | index |
346356
| test.cpp:849:5:849:22 | ... = ... | test.cpp:848:20:848:37 | call to malloc | test.cpp:849:5:849:22 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:848:20:848:37 | call to malloc | call to malloc | test.cpp:849:13:849:17 | index | index |
357+
| test.cpp:860:5:860:11 | ... = ... | test.cpp:856:12:856:35 | call to malloc | test.cpp:860:5:860:11 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:856:12:856:35 | call to malloc | call to malloc | test.cpp:857:21:857:28 | ... + ... | ... + ... |

cpp/ql/test/query-tests/Security/CWE/CWE-193/test.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -848,4 +848,15 @@ void test16_with_malloc(size_t index) {
848848
int* newname = (int*)malloc(size);
849849
newname[index] = 0; // $ SPURIOUS: alloc=L848 deref=L849 // GOOD [FALSE POSITIVE]
850850
}
851+
}
852+
853+
# define MyMalloc(size) malloc(((size) == 0 ? 1 : (size)))
854+
855+
void test_regression(size_t size) {
856+
int* p = (int*)MyMalloc(size + 1);
857+
int* chend = p + (size + 1); // $ alloc=L856+1
858+
859+
if(p <= chend) {
860+
*p = 42; // $ deref=L860 // BAD
861+
}
851862
}

0 commit comments

Comments
 (0)