Skip to content

Commit eb3f196

Browse files
authored
Merge pull request #14365 from MathiasVP/disable-flow-through-pointer-arith-for-size
C++: Disable size-flow through pointer arithmetics in `cpp/invalid-pointer-deref`
2 parents 97b3ebe + 843e9ad commit eb3f196

File tree

4 files changed

+28
-5
lines changed

4 files changed

+28
-5
lines changed

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ProductFlow.qll

+4
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,8 @@ module ProductFlow {
374374

375375
predicate isBarrier(DataFlow::Node node, FlowState state) { Config::isBarrier1(node, state) }
376376

377+
predicate isBarrier(DataFlow::Node node) { Config::isBarrier1(node) }
378+
377379
predicate isBarrierOut(DataFlow::Node node) { Config::isBarrierOut1(node) }
378380

379381
predicate isAdditionalFlowStep(
@@ -408,6 +410,8 @@ module ProductFlow {
408410

409411
predicate isBarrier(DataFlow::Node node, FlowState state) { Config::isBarrier2(node, state) }
410412

413+
predicate isBarrier(DataFlow::Node node) { Config::isBarrier2(node) }
414+
411415
predicate isBarrierOut(DataFlow::Node node) { Config::isBarrierOut2(node) }
412416

413417
predicate isAdditionalFlowStep(

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

+23
Original file line numberDiff line numberDiff line change
@@ -284,10 +284,33 @@ private module Config implements ProductFlow::StateConfigSig {
284284
pointerAddInstructionHasBounds0(_, allocSink, sizeSink, sizeAddend)
285285
}
286286

287+
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
288+
287289
predicate isBarrier2(DataFlow::Node node, FlowState2 state) {
288290
node = SizeBarrier::getABarrierNode(state)
289291
}
290292

293+
predicate isBarrier2(DataFlow::Node node) {
294+
// Block flow from `*p` to `*(p + n)` when `n` is not `0`. This removes
295+
// false positives
296+
// when tracking the size of the allocation as an element of an array such
297+
// as:
298+
// ```
299+
// size_t* p = new size_t[n];
300+
// ...
301+
// p[0] = n;
302+
// int i = p[1];
303+
// p[i] = ...
304+
// ```
305+
// In the above case, this barrier blocks flow from the indirect node
306+
// for `p` to `p[1]`.
307+
exists(Operand operand, PointerAddInstruction add |
308+
node.(IndirectOperand).hasOperandAndIndirectionIndex(operand, _) and
309+
add.getLeftOperand() = operand and
310+
add.getRight().(ConstantInstruction).getValue() != "0"
311+
)
312+
}
313+
291314
predicate isBarrierIn1(DataFlow::Node node) { isSourcePair(node, _, _, _) }
292315

293316
predicate isBarrierOut2(DataFlow::Node node) {

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

-4
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ edges
4646
| test.cpp:206:17:206:23 | ... + ... | test.cpp:213:5:213:13 | ... = ... |
4747
| test.cpp:231:18:231:30 | new[] | test.cpp:232:3:232:20 | ... = ... |
4848
| test.cpp:238:20:238:32 | new[] | test.cpp:239:5:239:22 | ... = ... |
49-
| test.cpp:248:13:248:36 | call to realloc | test.cpp:254:9:254:16 | ... = ... |
5049
| test.cpp:260:13:260:24 | new[] | test.cpp:261:14:261:21 | ... + ... |
5150
| test.cpp:260:13:260:24 | new[] | test.cpp:261:14:261:21 | ... + ... |
5251
| test.cpp:260:13:260:24 | new[] | test.cpp:264:13:264:14 | * ... |
@@ -215,8 +214,6 @@ nodes
215214
| test.cpp:232:3:232:20 | ... = ... | semmle.label | ... = ... |
216215
| test.cpp:238:20:238:32 | new[] | semmle.label | new[] |
217216
| test.cpp:239:5:239:22 | ... = ... | semmle.label | ... = ... |
218-
| test.cpp:248:13:248:36 | call to realloc | semmle.label | call to realloc |
219-
| test.cpp:254:9:254:16 | ... = ... | semmle.label | ... = ... |
220217
| test.cpp:260:13:260:24 | new[] | semmle.label | new[] |
221218
| test.cpp:261:14:261:21 | ... + ... | semmle.label | ... + ... |
222219
| test.cpp:261:14:261:21 | ... + ... | semmle.label | ... + ... |
@@ -322,7 +319,6 @@ subpaths
322319
| test.cpp:213:5:213:13 | ... = ... | test.cpp:205:15:205:33 | call to malloc | test.cpp:213:5:213:13 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:205:15:205:33 | call to malloc | call to malloc | test.cpp:206:21:206:23 | len | len |
323320
| test.cpp:232:3:232:20 | ... = ... | test.cpp:231:18:231:30 | new[] | test.cpp:232:3:232:20 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:231:18:231:30 | new[] | new[] | test.cpp:232:11:232:15 | index | index |
324321
| test.cpp:239:5:239:22 | ... = ... | test.cpp:238:20:238:32 | new[] | test.cpp:239:5:239:22 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:238:20:238:32 | new[] | new[] | test.cpp:239:13:239:17 | index | index |
325-
| test.cpp:254:9:254:16 | ... = ... | test.cpp:248:13:248:36 | call to realloc | test.cpp:254:9:254:16 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:248:13:248:36 | call to realloc | call to realloc | test.cpp:254:11:254:11 | i | i |
326322
| test.cpp:264:13:264:14 | * ... | test.cpp:260:13:260:24 | new[] | test.cpp:264:13:264:14 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:260:13:260:24 | new[] | new[] | test.cpp:261:19:261:21 | len | len |
327323
| test.cpp:274:5:274:10 | ... = ... | test.cpp:270:13:270:24 | new[] | test.cpp:274:5:274:10 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:270:13:270:24 | new[] | new[] | test.cpp:271:19:271:21 | len | len |
328324
| test.cpp:358:14:358:26 | end_plus_one indirection | test.cpp:355:14:355:27 | new[] | test.cpp:358:14:358:26 | end_plus_one indirection | This read might be out of bounds, as the pointer might be equal to $@ + $@ + 1. | test.cpp:355:14:355:27 | new[] | new[] | test.cpp:356:20:356:23 | size | size |

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ void test17(unsigned *p, unsigned x, unsigned k) {
251251
// The following access is okay because:
252252
// n = 3*p[0] + k >= p[0] + k >= p[1] + k > p[1] = i
253253
// (where p[0] denotes the original value for p[0])
254-
p[i] = x; // $ alloc=L248 deref=L254 // GOOD [FALSE POSITIVE]
254+
p[i] = x; // GOOD
255255
}
256256
}
257257

0 commit comments

Comments
 (0)