C++: Also account for setter-related flow and jump steps.

This commit is contained in:
Mathias Vorreiter Pedersen
2023-05-03 15:47:12 +01:00
parent 7fa6894aaf
commit 0d6fdc674b
3 changed files with 81 additions and 16 deletions

View File

@@ -1,6 +1,7 @@
import semmle.code.cpp.ir.dataflow.DataFlow import semmle.code.cpp.ir.dataflow.DataFlow
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplCommon
private import codeql.util.Unit private import codeql.util.Unit
module ProductFlow { module ProductFlow {
@@ -363,7 +364,40 @@ module ProductFlow {
TOutOf(DataFlowCall call) { TOutOf(DataFlowCall call) {
[any(Flow1::PathNode n).getNode(), any(Flow2::PathNode n).getNode()].(OutNode).getCall() = [any(Flow1::PathNode n).getNode(), any(Flow2::PathNode n).getNode()].(OutNode).getCall() =
call call
} } or
TJump()
private predicate into1(Flow1::PathNode pred1, Flow1::PathNode succ1, TKind kind) {
exists(DataFlowCall call |
kind = TInto(call) and
pred1.getNode().(ArgumentNode).getCall() = call and
succ1.getNode() instanceof ParameterNode
)
}
private predicate out1(Flow1::PathNode pred1, Flow1::PathNode succ1, TKind kind) {
exists(ReturnKindExt returnKind, DataFlowCall call |
kind = TOutOf(call) and
succ1.getNode() = returnKind.getAnOutNode(call) and
pred1.getNode().(ReturnNodeExt).getKind() = returnKind
)
}
private predicate into2(Flow2::PathNode pred1, Flow2::PathNode succ1, TKind kind) {
exists(DataFlowCall call |
kind = TInto(call) and
pred1.getNode().(ArgumentNode).getCall() = call and
succ1.getNode() instanceof ParameterNode
)
}
private predicate out2(Flow2::PathNode pred1, Flow2::PathNode succ1, TKind kind) {
exists(ReturnKindExt returnKind, DataFlowCall call |
kind = TOutOf(call) and
succ1.getNode() = returnKind.getAnOutNode(call) and
pred1.getNode().(ReturnNodeExt).getKind() = returnKind
)
}
pragma[nomagic] pragma[nomagic]
private predicate interprocEdge1( private predicate interprocEdge1(
@@ -374,14 +408,14 @@ module ProductFlow {
predDecl != succDecl and predDecl != succDecl and
pred1.getNode().getEnclosingCallable() = predDecl and pred1.getNode().getEnclosingCallable() = predDecl and
succ1.getNode().getEnclosingCallable() = succDecl and succ1.getNode().getEnclosingCallable() = succDecl and
exists(DataFlowCall call | (
kind = TInto(call) and into1(pred1, succ1, kind)
pred1.getNode().(ArgumentNode).getCall() = call and
succ1.getNode() instanceof ParameterNode
or or
kind = TOutOf(call) and out1(pred1, succ1, kind)
succ1.getNode().(OutNode).getCall() = call and or
pred1.getNode() instanceof ReturnNode kind = TJump() and
not into1(pred1, succ1, _) and
not out1(pred1, succ1, _)
) )
} }
@@ -394,14 +428,14 @@ module ProductFlow {
predDecl != succDecl and predDecl != succDecl and
pred2.getNode().getEnclosingCallable() = predDecl and pred2.getNode().getEnclosingCallable() = predDecl and
succ2.getNode().getEnclosingCallable() = succDecl and succ2.getNode().getEnclosingCallable() = succDecl and
exists(DataFlowCall call | (
kind = TInto(call) and into2(pred2, succ2, kind)
pred2.getNode().(ArgumentNode).getCall() = call and
succ2.getNode() instanceof ParameterNode
or or
kind = TOutOf(call) and out2(pred2, succ2, kind)
succ2.getNode().(OutNode).getCall() = call and or
pred2.getNode() instanceof ReturnNode kind = TJump() and
not into2(pred2, succ2, _) and
not out2(pred2, succ2, _)
) )
} }

View File

@@ -212,6 +212,15 @@ edges
| test.cpp:214:24:214:24 | p | test.cpp:216:10:216:10 | p | | 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: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:222:15:222:20 | buffer | test.cpp:214:24:214:24 | p |
| test.cpp:225:40:225:45 | buffer | test.cpp:226:5:226:26 | ... = ... |
| test.cpp:226:5:226:26 | ... = ... | test.cpp:226:12:226:17 | p_str indirection [post update] [string] |
| test.cpp:231:27:231:32 | call to malloc | test.cpp:232:22:232:27 | buffer |
| test.cpp:232:16:232:19 | set_string output argument [string] | test.cpp:233:12:233:14 | str indirection [string] |
| test.cpp:232:22:232:27 | buffer | test.cpp:225:40:225:45 | buffer |
| test.cpp:232:22:232:27 | buffer | test.cpp:232:16:232:19 | set_string output argument [string] |
| test.cpp:233:12:233:14 | str indirection [string] | test.cpp:233:12:233:21 | string |
| test.cpp:233:12:233:14 | str indirection [string] | test.cpp:233:16:233:21 | string indirection |
| test.cpp:233:16:233:21 | string indirection | test.cpp:233:12:233:21 | string |
nodes nodes
| test.cpp:16:11:16:21 | mk_string_t indirection [string] | semmle.label | mk_string_t indirection [string] | | 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 | ... = ... | | test.cpp:18:5:18:30 | ... = ... | semmle.label | ... = ... |
@@ -381,7 +390,17 @@ nodes
| test.cpp:216:10:216:10 | p | semmle.label | p | | 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:220:43:220:48 | call to malloc | semmle.label | call to malloc |
| test.cpp:222:15:222:20 | buffer | semmle.label | buffer | | test.cpp:222:15:222:20 | buffer | semmle.label | buffer |
| test.cpp:225:40:225:45 | buffer | semmle.label | buffer |
| test.cpp:226:5:226:26 | ... = ... | semmle.label | ... = ... |
| test.cpp:226:12:226:17 | p_str indirection [post update] [string] | semmle.label | p_str indirection [post update] [string] |
| test.cpp:231:27:231:32 | call to malloc | semmle.label | call to malloc |
| test.cpp:232:16:232:19 | set_string output argument [string] | semmle.label | set_string output argument [string] |
| test.cpp:232:22:232:27 | buffer | semmle.label | buffer |
| test.cpp:233:12:233:14 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:233:12:233:21 | string | semmle.label | string |
| test.cpp:233:16:233:21 | string indirection | semmle.label | string indirection |
subpaths subpaths
| test.cpp:232:22:232:27 | buffer | test.cpp:225:40:225:45 | buffer | test.cpp:226:12:226:17 | p_str indirection [post update] [string] | test.cpp:232:16:232:19 | set_string output argument [string] |
#select #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 | | 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 |
| test.cpp:72:9:72:15 | call to strncpy | test.cpp:18:19:18:24 | call to malloc | test.cpp:72:22:72:27 | string | This write may overflow $@ by 1 element. | test.cpp:72:22:72:27 | string | string | | test.cpp:72:9:72:15 | call to strncpy | test.cpp:18:19:18:24 | call to malloc | test.cpp:72:22:72:27 | string | This write may overflow $@ by 1 element. | test.cpp:72:22:72:27 | string | string |
@@ -398,3 +417,4 @@ subpaths
| test.cpp:199:9:199:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:199:22:199:27 | string | This write may overflow $@ by 2 elements. | test.cpp:199:22:199:27 | string | string | | test.cpp:199:9:199:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:199:22:199:27 | string | This write may overflow $@ by 2 elements. | test.cpp:199:22:199:27 | string | string |
| 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: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: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:233:5:233:10 | call to memset | test.cpp:231:27:231:32 | call to malloc | test.cpp:233:12:233:21 | string | This write may overflow $@ by 1 element. | test.cpp:233:16:233:21 | string | string |

View File

@@ -221,3 +221,14 @@ void test_missing_call_context(unsigned char *unrelated_buffer, unsigned size) {
call_memset(unrelated_buffer, size + 5); call_memset(unrelated_buffer, size + 5);
call_memset(buffer, size); call_memset(buffer, size);
} }
void set_string(string_t* p_str, char* buffer) {
p_str->string = buffer;
}
void test_flow_through_setter(unsigned size) {
string_t str;
char* buffer = (char*)malloc(size);
set_string(&str, buffer);
memset(str.string, 0, size + 1); // BAD
}