From a09a8dba95f817ff12100edfe0314f783acf4c03 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 4 May 2023 16:59:18 +0100 Subject: [PATCH 1/3] C++: Add testcase with repeated TP alerts. --- .../CWE-119/OverrunWriteProductFlow.expected | 35 +++++++++++++++++++ .../query-tests/Security/CWE/CWE-119/test.cpp | 10 ++++++ 2 files changed, 45 insertions(+) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected index 69174ec8f91..28d89d1924a 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected @@ -212,6 +212,7 @@ edges | test.cpp:214:24:214:24 | p | test.cpp:216:10:216:10 | p | | test.cpp:220:43:220:48 | call to malloc | test.cpp:222:15:222:20 | buffer | | test.cpp:222:15:222:20 | buffer | test.cpp:214:24:214:24 | p | +| test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | nodes | test.cpp:16:11:16:21 | mk_string_t indirection [string] | semmle.label | mk_string_t indirection [string] | | test.cpp:18:5:18:30 | ... = ... | semmle.label | ... = ... | @@ -381,6 +382,8 @@ nodes | test.cpp:216:10:216:10 | p | semmle.label | p | | test.cpp:220:43:220:48 | call to malloc | semmle.label | call to malloc | | test.cpp:222:15:222:20 | buffer | semmle.label | buffer | +| test.cpp:228:43:228:48 | call to malloc | semmle.label | call to malloc | +| test.cpp:232:10:232:15 | buffer | semmle.label | buffer | subpaths #select | test.cpp:42:5:42:11 | call to strncpy | test.cpp:18:19:18:24 | call to malloc | test.cpp:42:18:42:23 | string | This write may overflow $@ by 1 element. | test.cpp:42:18:42:23 | string | string | @@ -399,3 +402,35 @@ subpaths | test.cpp:203:9:203:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:203:22:203:27 | string | This write may overflow $@ by 2 elements. | test.cpp:203:22:203:27 | string | string | | test.cpp:207:9:207:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:207:22:207:27 | string | This write may overflow $@ by 3 elements. | test.cpp:207:22:207:27 | string | string | | test.cpp:216:3:216:8 | call to memset | test.cpp:220:43:220:48 | call to malloc | test.cpp:216:10:216:10 | p | This write may overflow $@ by 5 elements. | test.cpp:216:10:216:10 | p | p | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 1 element. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 2 elements. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 3 elements. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 4 elements. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 5 elements. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 6 elements. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 7 elements. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 8 elements. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 9 elements. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 10 elements. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 11 elements. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 12 elements. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 13 elements. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 14 elements. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 15 elements. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 16 elements. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 17 elements. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 18 elements. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 19 elements. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 20 elements. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 21 elements. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 22 elements. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 23 elements. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 24 elements. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 25 elements. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 26 elements. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 27 elements. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 28 elements. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 29 elements. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 30 elements. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 31 elements. | test.cpp:232:10:232:15 | buffer | buffer | +| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 32 elements. | test.cpp:232:10:232:15 | buffer | buffer | diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/test.cpp b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/test.cpp index 8ce2be9cd10..53e3e8dd032 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/test.cpp +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/test.cpp @@ -220,4 +220,14 @@ void test_missing_call_context(unsigned char *unrelated_buffer, unsigned size) { unsigned char* buffer = (unsigned char*)malloc(size); call_memset(unrelated_buffer, size + 5); call_memset(buffer, size); +} + +bool unknown(); + +void repeated_alerts(unsigned size, unsigned offset) { + unsigned char* buffer = (unsigned char*)malloc(size); + while(unknown()) { + ++size; + } + memset(buffer, 0, size); // BAD } \ No newline at end of file From 2587f8ed9625981e61592a279f20c59503697432 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 4 May 2023 17:29:31 +0100 Subject: [PATCH 2/3] C++: Only alert on the largest possible overflow. --- .../Likely Bugs/OverrunWriteProductFlow.ql | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql b/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql index 7c982b09151..128d766d3b9 100644 --- a/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql +++ b/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql @@ -134,16 +134,34 @@ module StringSizeConfig implements ProductFlow::StateConfigSig { module StringSizeFlow = ProductFlow::GlobalWithState; +int getOverflow( + DataFlow::Node source1, DataFlow::Node source2, DataFlow::Node sink1, DataFlow::Node sink2, + CallInstruction c, Expr buffer +) { + result > 0 and + exists( + StringSizeFlow::PathNode1 pathSource1, StringSizeFlow::PathNode2 pathSource2, + StringSizeFlow::PathNode1 pathSink1, StringSizeFlow::PathNode2 pathSink2 + | + StringSizeFlow::flowPath(pathSource1, pathSource2, pathSink1, pathSink2) and + source1 = pathSource1.getNode() and + source2 = pathSource2.getNode() and + sink1 = pathSink1.getNode() and + sink2 = pathSink2.getNode() and + isSinkPairImpl(c, sink1, sink2, result + pathSink2.getState(), buffer) + ) +} + from StringSizeFlow::PathNode1 source1, StringSizeFlow::PathNode2 source2, - StringSizeFlow::PathNode1 sink1, StringSizeFlow::PathNode2 sink2, int overflow, int sinkState, - CallInstruction c, DataFlow::Node sourceNode, Expr buffer, string element + StringSizeFlow::PathNode1 sink1, StringSizeFlow::PathNode2 sink2, int overflow, CallInstruction c, + Expr buffer, string element where StringSizeFlow::flowPath(source1, source2, sink1, sink2) and - sinkState = sink2.getState() and - isSinkPairImpl(c, sink1.getNode(), sink2.getNode(), overflow + sinkState, buffer) and - overflow > 0 and - sourceNode = source1.getNode() and + overflow = + max(getOverflow(source1.getNode(), source2.getNode(), sink1.getNode(), sink2.getNode(), c, + buffer) + ) and if overflow = 1 then element = " element." else element = " elements." select c.getUnconvertedResultExpression(), source1, sink1, "This write may overflow $@ by " + overflow + element, buffer, buffer.toString() From de08ada0bc3aee4a0beb6494326f1e9da4c0f31f Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 4 May 2023 17:29:39 +0100 Subject: [PATCH 3/3] C++: Accept test changes. --- .../CWE-119/OverrunWriteProductFlow.expected | 31 ------------------- 1 file changed, 31 deletions(-) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected index 28d89d1924a..87df87503e0 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected @@ -402,35 +402,4 @@ subpaths | test.cpp:203:9:203:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:203:22:203:27 | string | This write may overflow $@ by 2 elements. | test.cpp:203:22:203:27 | string | string | | test.cpp:207:9:207:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:207:22:207:27 | string | This write may overflow $@ by 3 elements. | test.cpp:207:22:207:27 | string | string | | test.cpp:216:3:216:8 | call to memset | test.cpp:220:43:220:48 | call to malloc | test.cpp:216:10:216:10 | p | This write may overflow $@ by 5 elements. | test.cpp:216:10:216:10 | p | p | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 1 element. | test.cpp:232:10:232:15 | buffer | buffer | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 2 elements. | test.cpp:232:10:232:15 | buffer | buffer | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 3 elements. | test.cpp:232:10:232:15 | buffer | buffer | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 4 elements. | test.cpp:232:10:232:15 | buffer | buffer | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 5 elements. | test.cpp:232:10:232:15 | buffer | buffer | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 6 elements. | test.cpp:232:10:232:15 | buffer | buffer | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 7 elements. | test.cpp:232:10:232:15 | buffer | buffer | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 8 elements. | test.cpp:232:10:232:15 | buffer | buffer | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 9 elements. | test.cpp:232:10:232:15 | buffer | buffer | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 10 elements. | test.cpp:232:10:232:15 | buffer | buffer | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 11 elements. | test.cpp:232:10:232:15 | buffer | buffer | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 12 elements. | test.cpp:232:10:232:15 | buffer | buffer | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 13 elements. | test.cpp:232:10:232:15 | buffer | buffer | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 14 elements. | test.cpp:232:10:232:15 | buffer | buffer | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 15 elements. | test.cpp:232:10:232:15 | buffer | buffer | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 16 elements. | test.cpp:232:10:232:15 | buffer | buffer | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 17 elements. | test.cpp:232:10:232:15 | buffer | buffer | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 18 elements. | test.cpp:232:10:232:15 | buffer | buffer | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 19 elements. | test.cpp:232:10:232:15 | buffer | buffer | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 20 elements. | test.cpp:232:10:232:15 | buffer | buffer | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 21 elements. | test.cpp:232:10:232:15 | buffer | buffer | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 22 elements. | test.cpp:232:10:232:15 | buffer | buffer | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 23 elements. | test.cpp:232:10:232:15 | buffer | buffer | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 24 elements. | test.cpp:232:10:232:15 | buffer | buffer | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 25 elements. | test.cpp:232:10:232:15 | buffer | buffer | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 26 elements. | test.cpp:232:10:232:15 | buffer | buffer | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 27 elements. | test.cpp:232:10:232:15 | buffer | buffer | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 28 elements. | test.cpp:232:10:232:15 | buffer | buffer | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 29 elements. | test.cpp:232:10:232:15 | buffer | buffer | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 30 elements. | test.cpp:232:10:232:15 | buffer | buffer | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 31 elements. | test.cpp:232:10:232:15 | buffer | buffer | | test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 32 elements. | test.cpp:232:10:232:15 | buffer | buffer |