Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit aa8214a

Browse files
committed
C++: Simplify 'Buffer.qll' by avoiding 'asIndirectExpr'. This removes the flow from 'x' to 'x++', which makes the whole library a lot simpler.
1 parent 18d3801 commit aa8214a

4 files changed

Lines changed: 14 additions & 96 deletions

File tree

cpp/ql/lib/semmle/code/cpp/commons/Buffer.qll

Lines changed: 9 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,6 @@ predicate memberMayBeVarSize(Class c, MemberVariable v) {
2424
exists(ArrayType t | t = v.getUnspecifiedType() | not t.getArraySize() > 1)
2525
}
2626

27-
/**
28-
* Gets the expression associated with `n`. Unlike `n.asExpr()` this also gets the
29-
* expression underlying an indirect dataflow node.
30-
*/
31-
private Expr getExpr(DataFlow::Node n, boolean isIndirect) {
32-
result = n.asExpr() and isIndirect = false
33-
or
34-
result = n.asIndirectExpr() and isIndirect = true
35-
}
36-
37-
private DataFlow::Node exprNode(Expr e, boolean isIndirect) { e = getExpr(result, isIndirect) }
38-
3927
/**
4028
* Holds if `bufferExpr` is an allocation-like expression.
4129
*
@@ -85,77 +73,17 @@ private int isSource(Expr bufferExpr, Element why) {
8573
)
8674
}
8775

88-
/** Holds if the value of `n2 + delta` may be equal to the value of `n1`. */
89-
private predicate localFlowIncrStep(DataFlow::Node n1, DataFlow::Node n2, int delta) {
90-
DataFlow::localFlowStep(n1, n2) and
91-
(
92-
exists(IncrementOperation incr |
93-
n1.asIndirectExpr() = incr.getOperand() and
94-
delta = -1
95-
)
96-
or
97-
exists(DecrementOperation decr |
98-
n1.asIndirectExpr() = decr.getOperand() and
99-
delta = 1
100-
)
101-
or
102-
exists(AddExpr add, Expr e1, Expr e2 |
103-
add.hasOperands(e1, e2) and
104-
n1.asIndirectExpr() = e1 and
105-
delta = -e2.getValue().toInt()
106-
)
107-
or
108-
exists(SubExpr add, Expr e1, Expr e2 |
109-
add.hasOperands(e1, e2) and
110-
n1.asIndirectExpr() = e1 and
111-
delta = e2.getValue().toInt()
112-
)
113-
)
114-
}
115-
116-
/**
117-
* Holds if `n1` may flow to `n2` without passing through any back-edges.
118-
*
119-
* Back-edges are excluded to prevent infinite loops on examples like:
120-
* ```
121-
* while(true) { ++n; }
122-
* ```
123-
* which, when used in `localFlowStepRec`, would create infinite loop that continuously
124-
* increments the `delta` parameter.
125-
*/
126-
private predicate localFlowNotIncrStep(DataFlow::Node n1, DataFlow::Node n2) {
127-
not localFlowIncrStep(n1, n2, _) and
128-
DataFlow::localFlowStep(n1, n2) and
129-
not n1 = n2.(DataFlow::SsaPhiNode).getAnInput(true)
130-
}
131-
13276
private predicate localFlowToExprStep(DataFlow::Node n1, DataFlow::Node n2) {
133-
not exists([n1.asExpr(), n1.asIndirectExpr()]) and
134-
localFlowNotIncrStep(n1, n2)
135-
}
136-
137-
/** Holds if `mid2 + delta` may be equal to `n1`. */
138-
private predicate localFlowStepRec0(DataFlow::Node n1, DataFlow::Node mid2, int delta) {
139-
exists(DataFlow::Node mid1, int d1, int d2 |
140-
// Or we take a number of steps that adds `d1` to the pointer
141-
localFlowStepRec(n1, mid1, d1) and
142-
// followed by a step that adds `d2` to the pointer
143-
localFlowIncrStep(mid1, mid2, d2) and
144-
delta = d1 + d2
145-
)
77+
not exists(n2.asExpr()) and
78+
DataFlow::localFlowStep(n1, n2)
14679
}
14780

14881
/** Holds if `n2 + delta` may be equal to `n1`. */
149-
private predicate localFlowStepRec(DataFlow::Node n1, DataFlow::Node n2, int delta) {
150-
// Either we take one or more steps that doesn't modify the size of the buffer
151-
localFlowNotIncrStep+(n1, n2) and
152-
delta = 0
153-
or
154-
exists(DataFlow::Node mid2 |
155-
// Or we step from `n1` to `mid2 + delta`
156-
localFlowStepRec0(n1, mid2, delta) and
157-
// and finally to the next `ExprNode`.
158-
localFlowToExprStep*(mid2, n2)
82+
private predicate localFlowStepToExpr(DataFlow::Node n1, Expr e2) {
83+
exists(DataFlow::Node mid, DataFlow::Node n2 |
84+
localFlowToExprStep*(n1, mid) and
85+
DataFlow::localFlowStep(mid, n2) and
86+
n2.asExpr() = e2
15987
)
16088
}
16189

@@ -181,9 +109,8 @@ private predicate step(Expr e1, Expr e2, int delta) {
181109
delta = bufferSize - parentClass.getSize()
182110
)
183111
or
184-
exists(boolean isIndirect |
185-
localFlowStepRec(exprNode(e1, isIndirect), exprNode(e2, isIndirect), delta)
186-
)
112+
localFlowStepToExpr(DataFlow::exprNode(e1), e2) and
113+
delta = 0
187114
}
188115

189116
/**

cpp/ql/test/query-tests/Security/CWE/CWE-119/semmle/tests/OverflowBuffer.expected

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
| overflowdestination.cpp:46:2:46:7 | call to memcpy | This 'memcpy' operation accesses 128 bytes but the $@ is only 64 bytes. | overflowdestination.cpp:40:7:40:10 | dest | destination buffer |
2-
| tests.cpp:23:2:23:7 | call to memcpy | This 'memcpy' operation accesses 20 bytes but the $@ is only 10 bytes. | tests.cpp:19:7:19:17 | smallbuffer | destination buffer |
32
| tests.cpp:23:2:23:7 | call to memcpy | This 'memcpy' operation accesses 20 bytes but the $@ is only 10 bytes. | tests.cpp:19:7:19:17 | smallbuffer | source buffer |
43
| tests.cpp:25:2:25:7 | call to memcpy | This 'memcpy' operation accesses 20 bytes but the $@ is only 10 bytes. | tests.cpp:19:7:19:17 | smallbuffer | destination buffer |
5-
| tests.cpp:25:2:25:7 | call to memcpy | This 'memcpy' operation accesses 20 bytes but the $@ is only 10 bytes. | tests.cpp:19:7:19:17 | smallbuffer | source buffer |
64
| tests.cpp:172:23:172:31 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:170:17:170:41 | {...} | array |
75
| tests.cpp:176:23:176:30 | access to array | This array indexing operation accesses byte offset 31 but the $@ is only 24 bytes. | tests.cpp:170:17:170:41 | {...} | array |
86
| tests.cpp:222:3:222:8 | call to memset | This 'memset' operation accesses 33 bytes but the $@ is only 32 bytes. | tests.cpp:214:8:214:14 | buffer1 | destination buffer |
@@ -38,19 +36,14 @@
3836
| tests.cpp:376:3:376:13 | access to array | This array indexing operation accesses byte offset 101 but the $@ is only 101 bytes. | tests.cpp:369:47:369:52 | call to malloc | array |
3937
| tests.cpp:446:3:446:24 | access to array | This array indexing operation accesses a negative index -3 on the $@. | tests.cpp:444:7:444:14 | intArray | array |
4038
| tests.cpp:454:3:454:11 | access to array | This array indexing operation accesses a negative index -21 on the $@. | tests.cpp:450:7:450:11 | multi | array |
41-
| tests.cpp:455:3:455:14 | access to array | This array indexing operation accesses a negative index -5 on the $@. | tests.cpp:450:7:450:11 | multi | array |
4239
| tests.cpp:456:3:456:11 | access to array | This array indexing operation accesses a negative index -21 on the $@. | tests.cpp:450:7:450:11 | multi | array |
43-
| tests.cpp:456:3:456:15 | access to array | This array indexing operation accesses a negative index -5 on the $@. | tests.cpp:450:7:450:11 | multi | array |
44-
| tests.cpp:457:3:457:14 | access to array | This array indexing operation accesses a negative index -5 on the $@. | tests.cpp:450:7:450:11 | multi | array |
4540
| tests.cpp:459:3:459:11 | access to array | This array indexing operation accesses byte offset 639 but the $@ is only 400 bytes. | tests.cpp:450:7:450:11 | multi | array |
4641
| tests.cpp:461:3:461:11 | access to array | This array indexing operation accesses byte offset 639 but the $@ is only 400 bytes. | tests.cpp:450:7:450:11 | multi | array |
4742
| tests.cpp:476:2:476:7 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:469:7:469:12 | buffer | array |
4843
| tests.cpp:477:2:477:7 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:469:7:469:12 | buffer | array |
49-
| tests.cpp:479:2:479:7 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:469:7:469:12 | buffer | array |
5044
| tests.cpp:481:2:481:7 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:469:7:469:12 | buffer | array |
5145
| tests.cpp:485:2:485:7 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:469:7:469:12 | buffer | array |
5246
| tests.cpp:487:2:487:7 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:473:21:473:26 | call to malloc | array |
53-
| tests.cpp:489:2:489:7 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:473:21:473:26 | call to malloc | array |
5447
| tests.cpp:491:2:491:7 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:474:21:474:26 | call to malloc | array |
5548
| tests.cpp:495:2:495:7 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:474:21:474:26 | call to malloc | array |
5649
| tests.cpp:519:3:519:8 | call to memset | This 'memset' operation accesses 20 bytes but the $@ is only 10 bytes. | tests.cpp:502:15:502:20 | call to malloc | destination buffer |
@@ -59,7 +52,6 @@
5952
| tests.cpp:541:6:541:10 | call to fread | This 'fread' operation may access 101 bytes but the $@ is only 100 bytes. | tests.cpp:532:7:532:16 | charBuffer | destination buffer |
6053
| tests.cpp:546:6:546:10 | call to fread | This 'fread' operation may access 400 bytes but the $@ is only 100 bytes. | tests.cpp:532:7:532:16 | charBuffer | destination buffer |
6154
| tests.cpp:569:6:569:15 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:565:7:565:12 | buffer | array |
62-
| tests.cpp:575:7:575:13 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:565:7:565:12 | buffer | array |
6355
| tests.cpp:577:7:577:13 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:565:7:565:12 | buffer | array |
6456
| tests.cpp:579:6:579:12 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:565:7:565:12 | buffer | array |
6557
| tests.cpp:586:6:586:12 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:565:7:565:12 | buffer | array |

cpp/ql/test/query-tests/Security/CWE/CWE-119/semmle/tests/OverflowStatic.expected

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
| overflowdestination.cpp:46:20:46:30 | sizeof(<expr>) | Potential buffer-overflow: 'dest' has size 64 not 128. |
2-
| tests.cpp:23:33:23:49 | sizeof(<expr>) | Potential buffer-overflow: 'bigbuffer' has size 10 not 20. |
32
| tests.cpp:25:33:25:49 | sizeof(<expr>) | Potential buffer-overflow: 'smallbuffer' has size 10 not 20. |
43
| tests.cpp:163:3:163:11 | access to array | Potential buffer-overflow: counter 'k' <= 100 but 'buffer' has 100 elements. |
54
| tests.cpp:164:8:164:16 | access to array | Potential buffer-overflow: counter 'k' <= 100 but 'buffer' has 100 elements. |

cpp/ql/test/query-tests/Security/CWE/CWE-119/semmle/tests/tests.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ void test1()
2020
char bigbuffer[20];
2121

2222
memcpy(bigbuffer, smallbuffer, sizeof(smallbuffer)); // GOOD
23-
memcpy(bigbuffer, smallbuffer, sizeof(bigbuffer)); // BAD: over-read
23+
memcpy(bigbuffer, smallbuffer, sizeof(bigbuffer)); // BAD: over-read [NOT DETECTED]
2424
memcpy(smallbuffer, bigbuffer, sizeof(smallbuffer)); // GOOD
2525
memcpy(smallbuffer, bigbuffer, sizeof(bigbuffer)); // BAD: over-write
2626
}
@@ -454,7 +454,7 @@ void test17(long long *longArray)
454454
multi[-5][5] = 0; // BAD: underrun write [INCORRECT MESSAGE]
455455
multi[5][-5] = 0; // DUBIOUS: underrun write (this one is still within the bounds of the whole array)
456456
multi[-5][-5] = 0; // BAD: underrun write [INCORRECT MESSAGE]
457-
multi[0][-5] = 0; // BAD: underrun write
457+
multi[0][-5] = 0; // BAD: underrun write [NOT DETECTED]
458458

459459
multi[15][5] = 0; // BAD: overrun write
460460
multi[5][15] = 0; // DUBIOUS: overrun write (this one is still within the bounds of the whole array)
@@ -476,7 +476,7 @@ void test18()
476476
p1[-1] = 0; // BAD: underrun write
477477
p2[-1] = 0; // BAD: underrun write
478478
p2++;
479-
p2[-1] = 0; // GOOD [FALSE POSITIVE]
479+
p2[-1] = 0; // GOOD
480480

481481
p3[-1] = 0; // BAD
482482
while (*p3 != 0) {
@@ -486,7 +486,7 @@ void test18()
486486

487487
p4[-1] = 0; // BAD: underrun write
488488
p4++;
489-
p4[-1] = 0; // GOOD [FALSE POSITIVE]
489+
p4[-1] = 0; // GOOD
490490

491491
p5[-1] = 0; // BAD
492492
while (*p5 != 0) {
@@ -572,7 +572,7 @@ void test21(bool cond)
572572
if (cond)
573573
{
574574
ptr++;
575-
if (ptr[-1] == 0) { return; } // GOOD: accesses buffer[0] [FALSE POSITIVE]
575+
if (ptr[-1] == 0) { return; } // GOOD: accesses buffer[0]
576576
} else {
577577
if (ptr[-1] == 0) { return; } // BAD: accesses buffer[-1]
578578
}

0 commit comments

Comments
 (0)