Skip to content

Commit 26c4a66

Browse files
committed
C++: Add range analysis to fix FPs.
1 parent df9981d commit 26c4a66

File tree

3 files changed

+14
-8
lines changed

3 files changed

+14
-8
lines changed

cpp/ql/src/Critical/OverflowStatic.ql

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import cpp
1616
import semmle.code.cpp.commons.Buffer
17+
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
1718
import LoopBounds
1819

1920
private predicate staticBufferBase(VariableAccess access, Variable v) {
@@ -51,6 +52,8 @@ predicate overflowOffsetInLoop(BufferAccess bufaccess, string msg) {
5152
loop.getStmt().getAChild*() = bufaccess.getEnclosingStmt() and
5253
loop.limit() >= bufaccess.bufferSize() and
5354
loop.counter().getAnAccess() = bufaccess.getArrayOffset() and
55+
// Ensure that we don't have an upper bound on the array index that's less than the buffer size.
56+
not upperBound(bufaccess.getArrayOffset().getFullyConverted()) < bufaccess.bufferSize() and
5457
msg =
5558
"Potential buffer-overflow: counter '" + loop.counter().toString() + "' <= " +
5659
loop.limit().toString() + " but '" + bufaccess.buffer().getName() + "' has " +
@@ -94,10 +97,15 @@ class CallWithBufferSize extends FunctionCall {
9497
}
9598

9699
int statedSizeValue() {
97-
exists(Expr statedSizeSrc |
98-
DataFlow::localExprFlow(statedSizeSrc, statedSizeExpr()) and
99-
result = statedSizeSrc.getValue().toInt()
100-
)
100+
// `upperBound(e)` defaults to `exprMaxVal(e)` when `e` isn't analyzable. So to get a meaningful
101+
// result in this case we pick the minimum value obtainable from dataflow and range analysis.
102+
result =
103+
upperBound(statedSizeExpr())
104+
.minimum(any(Expr statedSizeSrc |
105+
DataFlow::localExprFlow(statedSizeSrc, statedSizeExpr())
106+
|
107+
statedSizeSrc.getValue().toInt()
108+
))
101109
}
102110
}
103111

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
| tests.cpp:245:42:245:42 | 6 | Potential buffer-overflow: 'global_array_5' has size 5 not 6. |
66
| tests.cpp:349:2:349:14 | access to array | Potential buffer-overflow: 'charArray' has size 10 but 'charArray[10]' is accessed here. |
77
| tests.cpp:350:17:350:29 | access to array | Potential buffer-overflow: 'charArray' has size 10 but 'charArray[10]' is accessed here. |
8-
| tests.cpp:594:4:594:12 | access to array | Potential buffer-overflow: counter 'k' <= 100 but 'buffer' has 16 elements. |
9-
| tests.cpp:603:24:603:24 | n | Potential buffer-overflow: 'dest' has size 128 not 132. |
108
| var_size_struct.cpp:54:5:54:14 | access to array | Potential buffer-overflow: 'str' has size 1 but 'str[1]' is accessed here. |
119
| var_size_struct.cpp:55:5:55:14 | access to array | Potential buffer-overflow: 'str' has size 1 but 'str[1]' is accessed here. |
1210
| var_size_struct.cpp:103:39:103:41 | 129 | Potential buffer-overflow: 'str' has size 128 not 129. |

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,7 @@ void test22(bool b, const char* source) {
591591
int k;
592592
for (k = 0; k <= 100; k++) {
593593
if(k < 16) {
594-
buffer[k] = 'x'; // GOOD [FALSE POSITIVE]
594+
buffer[k] = 'x'; // GOOD
595595
}
596596
}
597597

@@ -600,7 +600,7 @@ void test22(bool b, const char* source) {
600600
if (n >= 128) {
601601
return;
602602
}
603-
memcpy(dest, source, n); // GOOD [FALSE POSITIVE]
603+
memcpy(dest, source, n); // GOOD
604604
}
605605

606606
int main(int argc, char *argv[])

0 commit comments

Comments
 (0)