Skip to content

Commit 4ad5923

Browse files
authored
Merge pull request #524 from geoffw0/cpp-299
CPP: Add (partial) dataflow to OverflowStatic.ql
2 parents 816a94e + cb609f4 commit 4ad5923

File tree

4 files changed

+39
-7
lines changed

4 files changed

+39
-7
lines changed

change-notes/1.19/analysis-cpp.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
| Resource not released in destructor | Fewer false positive results | Placement new is now excluded from the query. Also fixed an issue where false positives could occur if the destructor body was not in the snapshot. |
2626
| Missing return statement (`cpp/missing-return`) | Visible by default | The precision of this query has been increased from 'medium' to 'high', which makes it visible by default in LGTM. It was 'medium' in release 1.17 and 1.18 because it had false positives due to an extractor bug that was fixed in 1.18. |
2727
| Missing return statement | Fewer false positive results | The query is now produces correct results when a function returns a template-dependent type, or makes a non-returning call to another function. |
28+
| Static array access may cause overflow | More correct results | Data flow to the size argument of a buffer operation is now checked in this query. |
2829
| Call to memory access function may overflow buffer | More correct results | Array indexing with a negative index is now detected by this query. |
2930
| Self comparison | Fewer false positive results | Code inside macro invocations is now excluded from the query. |
3031
| Suspicious call to memset | Fewer false positive results | Types involving decltype are now correctly compared. |

cpp/ql/src/Critical/OverflowStatic.ql

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -82,22 +82,31 @@ class CallWithBufferSize extends FunctionCall
8282
Expr buffer() {
8383
exists(int i |
8484
bufferAndSizeFunction(this.getTarget(), i, _) and
85-
result = this.getArgument(i))
85+
result = this.getArgument(i)
86+
)
8687
}
87-
Expr statedSize() {
88+
Expr statedSizeExpr() {
8889
exists(int i |
8990
bufferAndSizeFunction(this.getTarget(), _, i) and
90-
result = this.getArgument(i))
91+
result = this.getArgument(i)
92+
)
93+
}
94+
int statedSizeValue() {
95+
exists(Expr statedSizeSrc |
96+
DataFlow::localFlow(DataFlow::exprNode(statedSizeSrc), DataFlow::exprNode(statedSizeExpr())) and
97+
result = statedSizeSrc.getValue().toInt()
98+
)
9199
}
92100
}
93101

94102
predicate wrongBufferSize(Expr error, string msg) {
95-
exists(CallWithBufferSize call, int bufsize, Variable buf |
103+
exists(CallWithBufferSize call, int bufsize, Variable buf, int statedSize |
96104
staticBuffer(call.buffer(), buf, bufsize) and
97-
call.statedSize().getValue().toInt() > bufsize and
98-
error = call.statedSize() and
105+
statedSize = min(call.statedSizeValue()) and
106+
statedSize > bufsize and
107+
error = call.statedSizeExpr() and
99108
msg = "Potential buffer-overflow: '" + buf.getName() +
100-
"' has size " + bufsize.toString() + " not " + call.statedSize().getValue() + ".")
109+
"' has size " + bufsize.toString() + " not " + statedSize + ".")
101110
}
102111

103112
predicate outOfBounds(BufferAccess bufaccess, string msg)

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@
66
| test.cpp:20:3:20:12 | access to array | Potential buffer-overflow: counter 'i' <= 3 but 'buffer2' has 3 elements. |
77
| test.cpp:24:27:24:27 | 4 | Potential buffer-overflow: 'buffer1' has size 3 not 4. |
88
| test.cpp:26:27:26:27 | 4 | Potential buffer-overflow: 'buffer2' has size 3 not 4. |
9+
| test.cpp:40:22:40:27 | amount | Potential buffer-overflow: 'buffer' has size 100 not 101. |

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,24 @@ void f1(void)
2525
memcpy(buffer2, buffer1, 3); // GOOD
2626
memcpy(buffer2, buffer1, 4); // BAD
2727
}
28+
29+
void f2(char *src)
30+
{
31+
char buffer[100];
32+
char *ptr;
33+
int amount;
34+
35+
amount = 100;
36+
memcpy(buffer, src, amount); // GOOD
37+
amount = amount + 1;
38+
memcpy(buffer, src, amount); // BAD [NOT DETECTED]
39+
amount = 101;
40+
memcpy(buffer, src, amount); // BAD
41+
42+
ptr = buffer;
43+
memcpy(ptr, src, 101); // BAD [NOT DETECTED]
44+
ptr = &(buffer[0]);
45+
memcpy(ptr, src, 101); // BAD [NOT DETECTED]
46+
ptr = &(buffer[1]);
47+
memcpy(ptr, src, 100); // BAD [NOT DETECTED]
48+
}

0 commit comments

Comments
 (0)