From bc8c6a7760cd700bd4b3404ece3b22c40538d2a6 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Fri, 24 Apr 2020 15:22:36 -0700 Subject: [PATCH 1/9] C++: pointer arg conflation in TaintTrackingUtil This brings the temporary conflation of pointers and objects at function arguments and parameters into TaintTrackingUtil, since we don't have precise flow for indirections yet. --- .../dataflow/internal/TaintTrackingUtil.qll | 28 +++++++++++++++++++ .../dataflow/taint-tests/test_diff.expected | 7 ----- .../dataflow/taint-tests/test_ir.expected | 8 ++++++ 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll index 2290bab05713..52650e3988c1 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll @@ -67,6 +67,22 @@ private predicate localInstructionTaintStep(Instruction nodeFrom, Instruction no or t instanceof ArrayType ) + or + // Until we have from through indirections across calls, we'll take flow out + // of the parameter and into its indirection. + exists(IRFunction f, Parameter parameter | + nodeFrom = getInitializeParameter(f, parameter) and + nodeTo = getInitializeIndirection(f, parameter) + ) + or + // Until we have flow through indirections across calls, we'll take flow out + // of the indirection and into the argument. + // When we get proper flow through indirections across calls, this code can be + // moved to `adjusedSink` or possibly into the `DataFlow::ExprNode` class. + exists(ReadSideEffectInstruction read | + read.getAnOperand().(SideEffectOperand).getAnyDef() = nodeFrom and + read.getArgumentDef() = nodeTo + ) } /** @@ -135,3 +151,15 @@ predicate modeledInstructionTaintStep(Instruction instrIn, Instruction instrOut) modelMidIn.isParameter(indexMid) ) } + +pragma[noinline] +private InitializeIndirectionInstruction getInitializeIndirection(IRFunction f, Parameter p) { + result.getParameter() = p and + result.getEnclosingIRFunction() = f +} + +pragma[noinline] +private InitializeParameterInstruction getInitializeParameter(IRFunction f, Parameter p) { + result.getParameter() = p and + result.getEnclosingIRFunction() = f +} \ No newline at end of file diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected index 58a7255accbd..0e703c8b86be 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected @@ -27,21 +27,14 @@ | taint.cpp:112:7:112:13 | taint.cpp:106:12:106:17 | IR only | | taint.cpp:130:7:130:9 | taint.cpp:127:8:127:13 | IR only | | taint.cpp:137:7:137:9 | taint.cpp:120:11:120:16 | AST only | -| taint.cpp:173:8:173:13 | taint.cpp:164:19:164:24 | AST only | -| taint.cpp:181:8:181:9 | taint.cpp:185:11:185:16 | AST only | -| taint.cpp:195:7:195:7 | taint.cpp:192:23:192:28 | AST only | | taint.cpp:195:7:195:7 | taint.cpp:193:6:193:6 | AST only | | taint.cpp:229:3:229:6 | taint.cpp:223:10:223:15 | AST only | | taint.cpp:233:8:233:8 | taint.cpp:223:10:223:15 | AST only | | taint.cpp:236:3:236:6 | taint.cpp:223:10:223:15 | AST only | | taint.cpp:244:3:244:6 | taint.cpp:223:10:223:15 | AST only | -| taint.cpp:256:8:256:8 | taint.cpp:223:10:223:15 | AST only | | taint.cpp:261:7:261:7 | taint.cpp:258:7:258:12 | AST only | | taint.cpp:351:7:351:7 | taint.cpp:330:6:330:11 | AST only | | taint.cpp:352:7:352:7 | taint.cpp:330:6:330:11 | AST only | -| taint.cpp:372:7:372:7 | taint.cpp:365:24:365:29 | AST only | -| taint.cpp:374:7:374:7 | taint.cpp:365:24:365:29 | AST only | -| taint.cpp:391:7:391:7 | taint.cpp:385:27:385:32 | AST only | | taint.cpp:423:7:423:7 | taint.cpp:422:14:422:19 | AST only | | taint.cpp:424:9:424:17 | taint.cpp:422:14:422:19 | AST only | | taint.cpp:429:7:429:7 | taint.cpp:428:13:428:18 | IR only | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected index 63ab09a46823..b0dcbc08745b 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected @@ -13,17 +13,25 @@ | taint.cpp:151:7:151:12 | call to select | taint.cpp:151:20:151:25 | call to source | | taint.cpp:167:8:167:13 | call to source | taint.cpp:167:8:167:13 | call to source | | taint.cpp:168:8:168:14 | tainted | taint.cpp:164:19:164:24 | call to source | +| taint.cpp:173:8:173:13 | array to pointer conversion | taint.cpp:164:19:164:24 | call to source | +| taint.cpp:181:8:181:9 | * ... | taint.cpp:185:11:185:16 | call to source | +| taint.cpp:195:7:195:7 | x | taint.cpp:192:23:192:28 | source | | taint.cpp:210:7:210:7 | x | taint.cpp:207:6:207:11 | call to source | | taint.cpp:215:7:215:7 | x | taint.cpp:207:6:207:11 | call to source | | taint.cpp:216:7:216:7 | y | taint.cpp:207:6:207:11 | call to source | | taint.cpp:250:8:250:8 | a | taint.cpp:223:10:223:15 | call to source | +| taint.cpp:256:8:256:8 | (reference dereference) | taint.cpp:223:10:223:15 | call to source | +| taint.cpp:256:8:256:8 | a | taint.cpp:223:10:223:15 | call to source | | taint.cpp:280:7:280:7 | t | taint.cpp:275:6:275:11 | call to source | | taint.cpp:289:7:289:7 | t | taint.cpp:275:6:275:11 | call to source | | taint.cpp:290:7:290:7 | x | taint.cpp:275:6:275:11 | call to source | | taint.cpp:291:7:291:7 | y | taint.cpp:275:6:275:11 | call to source | | taint.cpp:337:7:337:7 | t | taint.cpp:330:6:330:11 | call to source | | taint.cpp:350:7:350:7 | t | taint.cpp:330:6:330:11 | call to source | +| taint.cpp:372:7:372:7 | a | taint.cpp:365:24:365:29 | source | +| taint.cpp:374:7:374:7 | c | taint.cpp:365:24:365:29 | source | | taint.cpp:382:7:382:7 | a | taint.cpp:377:23:377:28 | source | +| taint.cpp:391:7:391:7 | a | taint.cpp:385:27:385:32 | source | | taint.cpp:429:7:429:7 | b | taint.cpp:428:13:428:18 | call to source | | taint.cpp:430:9:430:14 | member | taint.cpp:428:13:428:18 | call to source | | taint.cpp:465:7:465:7 | x | taint.cpp:462:6:462:11 | call to source | From 1650e07f19512acc2fa4e3dc130e3639fba1afb9 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Tue, 19 May 2020 11:07:12 -0700 Subject: [PATCH 2/9] C++: add local flow sources --- cpp/ql/src/semmle/code/cpp/models/Models.qll | 1 + .../cpp/models/implementations/Getenv.qll | 22 ++++++++ .../code/cpp/models/interfaces/FlowSource.qll | 12 +++- .../semmle/code/cpp/security/FlowSources.qll | 56 +++++++++++++++++-- 4 files changed, 86 insertions(+), 5 deletions(-) create mode 100644 cpp/ql/src/semmle/code/cpp/models/implementations/Getenv.qll diff --git a/cpp/ql/src/semmle/code/cpp/models/Models.qll b/cpp/ql/src/semmle/code/cpp/models/Models.qll index 82ae1fdc4f0a..32b7b172efc9 100644 --- a/cpp/ql/src/semmle/code/cpp/models/Models.qll +++ b/cpp/ql/src/semmle/code/cpp/models/Models.qll @@ -1,6 +1,7 @@ private import implementations.Allocation private import implementations.Deallocation private import implementations.Fread +private import implementations.Getenv private import implementations.Gets private import implementations.IdentityFunction private import implementations.Inet diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Getenv.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Getenv.qll new file mode 100644 index 000000000000..764a7dab5dca --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Getenv.qll @@ -0,0 +1,22 @@ +/** + * Provides an implementation class modelling the POSIX function `getenv`. + */ +import cpp +import semmle.code.cpp.models.interfaces.FlowSource + +/** + * The POSIX function `getenv`. + */ +class Getenv extends LocalFlowFunction { + Getenv() { + this.hasGlobalName("getenv") + } + + override predicate hasLocalFlowSource (FunctionOutput output, string description) { + ( + output.isReturnValueDeref() or + output.isReturnValue() + ) and + description = "an environment variable" + } +} \ No newline at end of file diff --git a/cpp/ql/src/semmle/code/cpp/models/interfaces/FlowSource.qll b/cpp/ql/src/semmle/code/cpp/models/interfaces/FlowSource.qll index 2c9effaff7cb..8952d7499428 100644 --- a/cpp/ql/src/semmle/code/cpp/models/interfaces/FlowSource.qll +++ b/cpp/ql/src/semmle/code/cpp/models/interfaces/FlowSource.qll @@ -11,7 +11,7 @@ import FunctionInputsAndOutputs import semmle.code.cpp.models.Models /** - * A library function which returns data read from a network connection. + * A library function which returns data that may be read from a network connection. */ abstract class RemoteFlowFunction extends Function { /** @@ -19,3 +19,13 @@ abstract class RemoteFlowFunction extends Function { */ abstract predicate hasRemoteFlowSource(FunctionOutput output, string description); } + +/** + * A library function which returns data that is directly controlled by a user. + */ +abstract class LocalFlowFunction extends Function { + /** + * Holds if data described by `description` flows from `output` of a call to this function. + */ + abstract predicate hasLocalFlowSource(FunctionOutput output, string description); +} \ No newline at end of file diff --git a/cpp/ql/src/semmle/code/cpp/security/FlowSources.qll b/cpp/ql/src/semmle/code/cpp/security/FlowSources.qll index eff40572c025..ed4a31263bef 100644 --- a/cpp/ql/src/semmle/code/cpp/security/FlowSources.qll +++ b/cpp/ql/src/semmle/code/cpp/security/FlowSources.qll @@ -13,10 +13,16 @@ abstract class RemoteFlowSource extends DataFlow::Node { abstract string getSourceType(); } -private class TaintedReturnSource extends RemoteFlowSource { +/** A data flow source of local user input. */ +abstract class LocalFlowSource extends DataFlow::Node { +/** Gets a string that describes the type of this local flow source. */ + abstract string getSourceType(); +} + +private class RemoteReturnSource extends RemoteFlowSource { string sourceType; - TaintedReturnSource() { + RemoteReturnSource() { exists(RemoteFlowFunction func, CallInstruction instr, FunctionOutput output | asInstruction() = instr and instr.getStaticCallTarget() = func and @@ -28,10 +34,10 @@ private class TaintedReturnSource extends RemoteFlowSource { override string getSourceType() { result = sourceType } } -private class TaintedParameterSource extends RemoteFlowSource { +private class RemoteParameterSource extends RemoteFlowSource { string sourceType; - TaintedParameterSource() { + RemoteParameterSource() { exists(RemoteFlowFunction func, WriteSideEffectInstruction instr, FunctionOutput output | asInstruction() = instr and instr.getPrimaryInstruction().(CallInstruction).getStaticCallTarget() = func and @@ -42,3 +48,45 @@ private class TaintedParameterSource extends RemoteFlowSource { override string getSourceType() { result = sourceType } } + +private class LocalReturnSource extends LocalFlowSource { + string sourceType; + + LocalReturnSource() { + exists(LocalFlowFunction func, CallInstruction instr, FunctionOutput output | + asInstruction() = instr and + instr.getStaticCallTarget() = func and + func.hasLocalFlowSource(output, sourceType) and + output.isReturnValue() + ) + } + + override string getSourceType() { result = sourceType } +} + +private class LocalParameterSource extends LocalFlowSource { + string sourceType; + + LocalParameterSource() { + exists(LocalFlowFunction func, WriteSideEffectInstruction instr, FunctionOutput output | + asInstruction() = instr and + instr.getPrimaryInstruction().(CallInstruction).getStaticCallTarget() = func and + func.hasLocalFlowSource(output, sourceType) and + output.isParameterDeref(instr.getIndex()) + ) + } + + override string getSourceType() { result = sourceType } +} + +private class ArgvSource extends LocalFlowSource { + ArgvSource() { + exists(Parameter argv | + argv.hasName("argv") and + argv.getFunction().hasGlobalName("main") and + this.asExpr() = argv.getAnAccess() + ) + } + + override string getSourceType() { result = "a command line argument" } +} \ No newline at end of file From 956a70da616039ab3bc2fc77c09be7cbcf2eb21e Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Tue, 28 Apr 2020 13:09:00 -0700 Subject: [PATCH 3/9] C++: Use TaintTracking::Conf in TaintedAllocationSize This migrates TaintedAllocationSize to use the standard TaintTracking::Configuration mechanism rather than DefaultTaintTracking. This includes a new SanitizerGuard instance, but it has some false positives where a variable is bounds checked and reassigned if out of bounds. --- .../CWE/CWE-190/TaintedAllocationSize.ql | 58 ++++++- .../cpp/ir/dataflow/internal/ModelUtil.qll | 2 +- .../TaintedAllocationSize.expected | 157 ++++++------------ .../TaintedAllocationSize/field_conflation.c | 2 +- .../semmle/TaintedAllocationSize/test.cpp | 6 +- 5 files changed, 102 insertions(+), 123 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql index 54c6d1e7a966..4fbac56f51ed 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql +++ b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql @@ -12,8 +12,10 @@ */ import cpp -import semmle.code.cpp.security.TaintTracking -import TaintedWithPath +import semmle.code.cpp.ir.dataflow.TaintTracking +import semmle.code.cpp.security.FlowSources +import DataFlow::PathGraph +import semmle.code.cpp.ir.IR /** * Holds if `alloc` is an allocation, and `tainted` is a child of it that is a @@ -25,21 +27,59 @@ predicate allocSink(Expr alloc, Expr tainted) { tainted.getUnspecifiedType() instanceof IntegralType } -class TaintedAllocationSizeConfiguration extends TaintTrackingConfiguration { - override predicate isSink(Element tainted) { allocSink(_, tainted) } +class TaintedAllocationSizeConfiguration extends TaintTracking::Configuration { + TaintedAllocationSizeConfiguration() { this = "TaintedAllocationSizeConfiguration" } + + override predicate isSource(DataFlow::Node source) { + source instanceof RemoteFlowSource or source instanceof LocalFlowSource + } + + override predicate isSink(DataFlow::Node sink) { allocSink(_, sink.asExpr()) } + + override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { + guard instanceof UpperBoundGuard + } +} + +class UpperBoundGuard extends DataFlow::BarrierGuard { + UpperBoundGuard() { + this.comparesLt(_, _, _, _, _) + } + + override predicate checks(Instruction i, boolean b) { + this.comparesLt(i.getAUse(), _, _, _, b) + } } +/* + * class TaintedAllocationSizeConfiguration extends TaintTrackingConfiguration { + * override predicate isSink(Element tainted) { allocSink(_, tainted) } + * } + */ + predicate taintedAllocSize( - Expr source, Expr alloc, PathNode sourceNode, PathNode sinkNode, string taintCause + Expr source, Expr alloc, DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode, + string taintCause ) { - isUserInput(source, taintCause) and - exists(Expr tainted | + exists(Expr tainted, DataFlow::Node rawSourceNode, TaintedAllocationSizeConfiguration config | allocSink(alloc, tainted) and - taintedWithPath(source, tainted, sourceNode, sinkNode) + ( + rawSourceNode.asExpr() = source or + rawSourceNode.asDefiningArgument() = source + ) and + sourceNode.getNode() = rawSourceNode and + config.hasFlowPath(sourceNode, sinkNode) and + tainted = sinkNode.getNode().(DataFlow::ExprNode).getConvertedExpr() and + ( + taintCause = rawSourceNode.(RemoteFlowSource).getSourceType() or + taintCause = rawSourceNode.(LocalFlowSource).getSourceType() + ) ) } -from Expr source, Expr alloc, PathNode sourceNode, PathNode sinkNode, string taintCause +from + Expr source, Expr alloc, DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode, + string taintCause where taintedAllocSize(source, alloc, sourceNode, sinkNode, taintCause) select alloc, sourceNode, sinkNode, "This allocation size is derived from $@ and might overflow", source, "user input (" + taintCause + ")" diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/ModelUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/ModelUtil.qll index d1cafb28f1c1..a779f4d170bf 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/ModelUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/ModelUtil.qll @@ -18,7 +18,7 @@ Instruction callInput(CallInstruction call, FunctionInput input) { or // A value pointed to by a positional argument exists(ReadSideEffectInstruction read | - result = read and + result = read.getSideEffectOperand().getAnyDef() and read.getPrimaryInstruction() = call and input.isParameterDeref(read.getIndex()) ) diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected index 803b330716ec..742a6fae314a 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected @@ -1,157 +1,96 @@ edges -| field_conflation.c:12:22:12:27 | call to getenv | field_conflation.c:13:3:13:18 | Chi | -| field_conflation.c:12:22:12:34 | (const char *)... | field_conflation.c:13:3:13:18 | Chi | -| field_conflation.c:13:3:13:18 | Chi | field_conflation.c:19:15:19:17 | taint_array output argument | -| field_conflation.c:19:15:19:17 | taint_array output argument | field_conflation.c:20:10:20:13 | (unsigned long)... | -| field_conflation.c:19:15:19:17 | taint_array output argument | field_conflation.c:20:13:20:13 | x | -| field_conflation.c:19:15:19:17 | taint_array output argument | field_conflation.c:20:13:20:13 | x | -| field_conflation.c:19:15:19:17 | taint_array output argument | field_conflation.c:20:13:20:13 | x | -| field_conflation.c:20:13:20:13 | x | field_conflation.c:20:10:20:13 | (unsigned long)... | -| field_conflation.c:20:13:20:13 | x | field_conflation.c:20:13:20:13 | x | | test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | (size_t)... | -| test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | (size_t)... | -| test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted | -| test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted | -| test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted | | test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted | | test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... | -| test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... | -| test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... | -| test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... | | test.cpp:39:21:39:24 | argv | test.cpp:45:38:45:63 | ... + ... | -| test.cpp:39:21:39:24 | argv | test.cpp:45:38:45:63 | ... + ... | -| test.cpp:39:21:39:24 | argv | test.cpp:45:38:45:63 | ... + ... | -| test.cpp:39:21:39:24 | argv | test.cpp:45:38:45:63 | ... + ... | -| test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | (size_t)... | | test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | (size_t)... | | test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | size | -| test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | size | -| test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | size | -| test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | size | | test.cpp:39:21:39:24 | argv | test.cpp:49:26:49:29 | size | -| test.cpp:39:21:39:24 | argv | test.cpp:49:26:49:29 | size | -| test.cpp:39:21:39:24 | argv | test.cpp:49:26:49:29 | size | -| test.cpp:39:21:39:24 | argv | test.cpp:49:26:49:29 | size | -| test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... | | test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... | -| test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... | -| test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... | -| test.cpp:123:18:123:23 | call to getenv | test.cpp:127:24:127:41 | ... * ... | +| test.cpp:75:25:75:29 | start | test.cpp:79:18:79:28 | ... - ... | +| test.cpp:75:38:75:40 | end | test.cpp:79:18:79:28 | ... - ... | +| test.cpp:97:18:97:23 | fread output argument | test.cpp:100:17:100:22 | array to pointer conversion | +| test.cpp:97:18:97:23 | fread output argument | test.cpp:101:17:101:22 | array to pointer conversion | +| test.cpp:97:18:97:23 | fread output argument | test.cpp:101:25:101:39 | ... + ... | +| test.cpp:100:17:100:22 | array to pointer conversion | test.cpp:100:17:100:22 | processData1 output argument | +| test.cpp:100:17:100:22 | processData1 output argument | test.cpp:101:17:101:22 | array to pointer conversion | +| test.cpp:100:17:100:22 | processData1 output argument | test.cpp:101:25:101:39 | ... + ... | +| test.cpp:101:17:101:22 | array to pointer conversion | test.cpp:75:25:75:29 | start | +| test.cpp:101:25:101:39 | ... + ... | test.cpp:75:38:75:40 | end | +| test.cpp:123:18:123:23 | call to getenv | test.cpp:124:29:124:32 | size | | test.cpp:123:18:123:23 | call to getenv | test.cpp:127:24:127:41 | ... * ... | -| test.cpp:123:18:123:31 | (const char *)... | test.cpp:127:24:127:41 | ... * ... | -| test.cpp:123:18:123:31 | (const char *)... | test.cpp:127:24:127:41 | ... * ... | +| test.cpp:124:21:124:27 | call to bounded | test.cpp:126:24:126:49 | ... * ... | +| test.cpp:124:29:124:32 | size | test.cpp:124:21:124:27 | call to bounded | | test.cpp:132:19:132:24 | call to getenv | test.cpp:134:10:134:27 | ... * ... | -| test.cpp:132:19:132:24 | call to getenv | test.cpp:134:10:134:27 | ... * ... | -| test.cpp:132:19:132:32 | (const char *)... | test.cpp:134:10:134:27 | ... * ... | -| test.cpp:132:19:132:32 | (const char *)... | test.cpp:134:10:134:27 | ... * ... | -| test.cpp:138:19:138:24 | call to getenv | test.cpp:142:11:142:28 | ... * ... | -| test.cpp:138:19:138:24 | call to getenv | test.cpp:142:11:142:28 | ... * ... | -| test.cpp:138:19:138:32 | (const char *)... | test.cpp:142:11:142:28 | ... * ... | -| test.cpp:138:19:138:32 | (const char *)... | test.cpp:142:11:142:28 | ... * ... | -| test.cpp:201:9:201:42 | Store | test.cpp:231:9:231:24 | call to get_tainted_size | +| test.cpp:174:19:174:24 | call to getenv | test.cpp:176:10:176:27 | ... * ... | | test.cpp:201:9:201:42 | Store | test.cpp:231:9:231:24 | call to get_tainted_size | | test.cpp:201:14:201:19 | call to getenv | test.cpp:201:9:201:42 | Store | -| test.cpp:201:14:201:27 | (const char *)... | test.cpp:201:9:201:42 | Store | -| test.cpp:214:23:214:23 | s | test.cpp:215:21:215:21 | s | +| test.cpp:206:18:206:23 | call to getenv | test.cpp:211:9:211:9 | Store | +| test.cpp:211:9:211:9 | Store | test.cpp:232:9:232:24 | call to get_bounded_size | | test.cpp:214:23:214:23 | s | test.cpp:215:21:215:21 | s | | test.cpp:220:21:220:21 | s | test.cpp:221:21:221:21 | s | -| test.cpp:220:21:220:21 | s | test.cpp:221:21:221:21 | s | | test.cpp:227:24:227:29 | call to getenv | test.cpp:229:9:229:18 | (size_t)... | | test.cpp:227:24:227:29 | call to getenv | test.cpp:229:9:229:18 | local_size | -| test.cpp:227:24:227:29 | call to getenv | test.cpp:229:9:229:18 | local_size | | test.cpp:227:24:227:29 | call to getenv | test.cpp:235:11:235:20 | (size_t)... | | test.cpp:227:24:227:29 | call to getenv | test.cpp:237:10:237:19 | (size_t)... | -| test.cpp:227:24:227:37 | (const char *)... | test.cpp:229:9:229:18 | (size_t)... | -| test.cpp:227:24:227:37 | (const char *)... | test.cpp:229:9:229:18 | local_size | -| test.cpp:227:24:227:37 | (const char *)... | test.cpp:229:9:229:18 | local_size | -| test.cpp:227:24:227:37 | (const char *)... | test.cpp:235:11:235:20 | (size_t)... | -| test.cpp:227:24:227:37 | (const char *)... | test.cpp:237:10:237:19 | (size_t)... | | test.cpp:235:11:235:20 | (size_t)... | test.cpp:214:23:214:23 | s | | test.cpp:237:10:237:19 | (size_t)... | test.cpp:220:21:220:21 | s | nodes -| field_conflation.c:12:22:12:27 | call to getenv | semmle.label | call to getenv | -| field_conflation.c:12:22:12:34 | (const char *)... | semmle.label | (const char *)... | -| field_conflation.c:13:3:13:18 | Chi | semmle.label | Chi | -| field_conflation.c:19:15:19:17 | taint_array output argument | semmle.label | taint_array output argument | -| field_conflation.c:20:10:20:13 | (unsigned long)... | semmle.label | (unsigned long)... | -| field_conflation.c:20:10:20:13 | (unsigned long)... | semmle.label | (unsigned long)... | -| field_conflation.c:20:13:20:13 | x | semmle.label | x | -| field_conflation.c:20:13:20:13 | x | semmle.label | x | -| field_conflation.c:20:13:20:13 | x | semmle.label | x | -| test.cpp:39:21:39:24 | argv | semmle.label | argv | | test.cpp:39:21:39:24 | argv | semmle.label | argv | | test.cpp:42:38:42:44 | (size_t)... | semmle.label | (size_t)... | -| test.cpp:42:38:42:44 | (size_t)... | semmle.label | (size_t)... | -| test.cpp:42:38:42:44 | tainted | semmle.label | tainted | | test.cpp:42:38:42:44 | tainted | semmle.label | tainted | -| test.cpp:42:38:42:44 | tainted | semmle.label | tainted | -| test.cpp:43:38:43:63 | ... * ... | semmle.label | ... * ... | | test.cpp:43:38:43:63 | ... * ... | semmle.label | ... * ... | -| test.cpp:43:38:43:63 | ... * ... | semmle.label | ... * ... | -| test.cpp:45:38:45:63 | ... + ... | semmle.label | ... + ... | -| test.cpp:45:38:45:63 | ... + ... | semmle.label | ... + ... | | test.cpp:45:38:45:63 | ... + ... | semmle.label | ... + ... | | test.cpp:48:32:48:35 | (size_t)... | semmle.label | (size_t)... | -| test.cpp:48:32:48:35 | (size_t)... | semmle.label | (size_t)... | -| test.cpp:48:32:48:35 | size | semmle.label | size | | test.cpp:48:32:48:35 | size | semmle.label | size | -| test.cpp:48:32:48:35 | size | semmle.label | size | -| test.cpp:49:26:49:29 | size | semmle.label | size | | test.cpp:49:26:49:29 | size | semmle.label | size | -| test.cpp:49:26:49:29 | size | semmle.label | size | -| test.cpp:52:35:52:60 | ... * ... | semmle.label | ... * ... | -| test.cpp:52:35:52:60 | ... * ... | semmle.label | ... * ... | | test.cpp:52:35:52:60 | ... * ... | semmle.label | ... * ... | +| test.cpp:75:25:75:29 | start | semmle.label | start | +| test.cpp:75:38:75:40 | end | semmle.label | end | +| test.cpp:79:18:79:28 | ... - ... | semmle.label | ... - ... | +| test.cpp:97:18:97:23 | fread output argument | semmle.label | fread output argument | +| test.cpp:100:17:100:22 | array to pointer conversion | semmle.label | array to pointer conversion | +| test.cpp:100:17:100:22 | processData1 output argument | semmle.label | processData1 output argument | +| test.cpp:101:17:101:22 | array to pointer conversion | semmle.label | array to pointer conversion | +| test.cpp:101:25:101:39 | ... + ... | semmle.label | ... + ... | | test.cpp:123:18:123:23 | call to getenv | semmle.label | call to getenv | -| test.cpp:123:18:123:31 | (const char *)... | semmle.label | (const char *)... | -| test.cpp:127:24:127:41 | ... * ... | semmle.label | ... * ... | -| test.cpp:127:24:127:41 | ... * ... | semmle.label | ... * ... | +| test.cpp:124:21:124:27 | call to bounded | semmle.label | call to bounded | +| test.cpp:124:29:124:32 | size | semmle.label | size | +| test.cpp:126:24:126:49 | ... * ... | semmle.label | ... * ... | | test.cpp:127:24:127:41 | ... * ... | semmle.label | ... * ... | | test.cpp:132:19:132:24 | call to getenv | semmle.label | call to getenv | -| test.cpp:132:19:132:32 | (const char *)... | semmle.label | (const char *)... | -| test.cpp:134:10:134:27 | ... * ... | semmle.label | ... * ... | -| test.cpp:134:10:134:27 | ... * ... | semmle.label | ... * ... | | test.cpp:134:10:134:27 | ... * ... | semmle.label | ... * ... | -| test.cpp:138:19:138:24 | call to getenv | semmle.label | call to getenv | -| test.cpp:138:19:138:32 | (const char *)... | semmle.label | (const char *)... | -| test.cpp:142:11:142:28 | ... * ... | semmle.label | ... * ... | -| test.cpp:142:11:142:28 | ... * ... | semmle.label | ... * ... | -| test.cpp:142:11:142:28 | ... * ... | semmle.label | ... * ... | +| test.cpp:174:19:174:24 | call to getenv | semmle.label | call to getenv | +| test.cpp:176:10:176:27 | ... * ... | semmle.label | ... * ... | | test.cpp:201:9:201:42 | Store | semmle.label | Store | | test.cpp:201:14:201:19 | call to getenv | semmle.label | call to getenv | -| test.cpp:201:14:201:27 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:206:18:206:23 | call to getenv | semmle.label | call to getenv | +| test.cpp:211:9:211:9 | Store | semmle.label | Store | | test.cpp:214:23:214:23 | s | semmle.label | s | | test.cpp:215:21:215:21 | s | semmle.label | s | -| test.cpp:215:21:215:21 | s | semmle.label | s | -| test.cpp:215:21:215:21 | s | semmle.label | s | | test.cpp:220:21:220:21 | s | semmle.label | s | | test.cpp:221:21:221:21 | s | semmle.label | s | -| test.cpp:221:21:221:21 | s | semmle.label | s | -| test.cpp:221:21:221:21 | s | semmle.label | s | | test.cpp:227:24:227:29 | call to getenv | semmle.label | call to getenv | -| test.cpp:227:24:227:37 | (const char *)... | semmle.label | (const char *)... | -| test.cpp:229:9:229:18 | (size_t)... | semmle.label | (size_t)... | | test.cpp:229:9:229:18 | (size_t)... | semmle.label | (size_t)... | | test.cpp:229:9:229:18 | local_size | semmle.label | local_size | -| test.cpp:229:9:229:18 | local_size | semmle.label | local_size | -| test.cpp:229:9:229:18 | local_size | semmle.label | local_size | -| test.cpp:231:9:231:24 | call to get_tainted_size | semmle.label | call to get_tainted_size | -| test.cpp:231:9:231:24 | call to get_tainted_size | semmle.label | call to get_tainted_size | | test.cpp:231:9:231:24 | call to get_tainted_size | semmle.label | call to get_tainted_size | +| test.cpp:232:9:232:24 | call to get_bounded_size | semmle.label | call to get_bounded_size | | test.cpp:235:11:235:20 | (size_t)... | semmle.label | (size_t)... | | test.cpp:237:10:237:19 | (size_t)... | semmle.label | (size_t)... | #select -| field_conflation.c:20:3:20:8 | call to malloc | field_conflation.c:12:22:12:27 | call to getenv | field_conflation.c:20:13:20:13 | x | This allocation size is derived from $@ and might overflow | field_conflation.c:12:22:12:27 | call to getenv | user input (getenv) | -| test.cpp:42:31:42:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | -| test.cpp:43:31:43:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | -| test.cpp:45:31:45:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:45:38:45:63 | ... + ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | -| test.cpp:48:25:48:30 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | size | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | -| test.cpp:49:17:49:30 | new[] | test.cpp:39:21:39:24 | argv | test.cpp:49:26:49:29 | size | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | -| test.cpp:52:21:52:27 | call to realloc | test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | -| test.cpp:127:17:127:22 | call to malloc | test.cpp:123:18:123:23 | call to getenv | test.cpp:127:24:127:41 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:123:18:123:23 | call to getenv | user input (getenv) | -| test.cpp:134:3:134:8 | call to malloc | test.cpp:132:19:132:24 | call to getenv | test.cpp:134:10:134:27 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:132:19:132:24 | call to getenv | user input (getenv) | -| test.cpp:142:4:142:9 | call to malloc | test.cpp:138:19:138:24 | call to getenv | test.cpp:142:11:142:28 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:138:19:138:24 | call to getenv | user input (getenv) | -| test.cpp:215:14:215:19 | call to malloc | test.cpp:227:24:227:29 | call to getenv | test.cpp:215:21:215:21 | s | This allocation size is derived from $@ and might overflow | test.cpp:227:24:227:29 | call to getenv | user input (getenv) | -| test.cpp:221:14:221:19 | call to malloc | test.cpp:227:24:227:29 | call to getenv | test.cpp:221:21:221:21 | s | This allocation size is derived from $@ and might overflow | test.cpp:227:24:227:29 | call to getenv | user input (getenv) | -| test.cpp:229:2:229:7 | call to malloc | test.cpp:227:24:227:29 | call to getenv | test.cpp:229:9:229:18 | local_size | This allocation size is derived from $@ and might overflow | test.cpp:227:24:227:29 | call to getenv | user input (getenv) | -| test.cpp:231:2:231:7 | call to malloc | test.cpp:201:14:201:19 | call to getenv | test.cpp:231:9:231:24 | call to get_tainted_size | This allocation size is derived from $@ and might overflow | test.cpp:201:14:201:19 | call to getenv | user input (getenv) | +| test.cpp:42:31:42:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (a command line argument) | +| test.cpp:43:31:43:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (a command line argument) | +| test.cpp:45:31:45:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:45:38:45:63 | ... + ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (a command line argument) | +| test.cpp:48:25:48:30 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | size | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (a command line argument) | +| test.cpp:49:17:49:30 | new[] | test.cpp:39:21:39:24 | argv | test.cpp:49:26:49:29 | size | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (a command line argument) | +| test.cpp:52:21:52:27 | call to realloc | test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (a command line argument) | +| test.cpp:79:9:79:29 | new[] | test.cpp:97:18:97:23 | fread output argument | test.cpp:79:18:79:28 | ... - ... | This allocation size is derived from $@ and might overflow | test.cpp:97:18:97:23 | buffer | user input (String read by fread) | +| test.cpp:126:17:126:22 | call to malloc | test.cpp:123:18:123:23 | call to getenv | test.cpp:126:24:126:49 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:123:18:123:23 | call to getenv | user input (an environment variable) | +| test.cpp:127:17:127:22 | call to malloc | test.cpp:123:18:123:23 | call to getenv | test.cpp:127:24:127:41 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:123:18:123:23 | call to getenv | user input (an environment variable) | +| test.cpp:134:3:134:8 | call to malloc | test.cpp:132:19:132:24 | call to getenv | test.cpp:134:10:134:27 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:132:19:132:24 | call to getenv | user input (an environment variable) | +| test.cpp:176:3:176:8 | call to malloc | test.cpp:174:19:174:24 | call to getenv | test.cpp:176:10:176:27 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:174:19:174:24 | call to getenv | user input (an environment variable) | +| test.cpp:215:14:215:19 | call to malloc | test.cpp:227:24:227:29 | call to getenv | test.cpp:215:21:215:21 | s | This allocation size is derived from $@ and might overflow | test.cpp:227:24:227:29 | call to getenv | user input (an environment variable) | +| test.cpp:221:14:221:19 | call to malloc | test.cpp:227:24:227:29 | call to getenv | test.cpp:221:21:221:21 | s | This allocation size is derived from $@ and might overflow | test.cpp:227:24:227:29 | call to getenv | user input (an environment variable) | +| test.cpp:229:2:229:7 | call to malloc | test.cpp:227:24:227:29 | call to getenv | test.cpp:229:9:229:18 | local_size | This allocation size is derived from $@ and might overflow | test.cpp:227:24:227:29 | call to getenv | user input (an environment variable) | +| test.cpp:231:2:231:7 | call to malloc | test.cpp:201:14:201:19 | call to getenv | test.cpp:231:9:231:24 | call to get_tainted_size | This allocation size is derived from $@ and might overflow | test.cpp:201:14:201:19 | call to getenv | user input (an environment variable) | +| test.cpp:232:2:232:7 | call to malloc | test.cpp:206:18:206:23 | call to getenv | test.cpp:232:9:232:24 | call to get_bounded_size | This allocation size is derived from $@ and might overflow | test.cpp:206:18:206:23 | call to getenv | user input (an environment variable) | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/field_conflation.c b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/field_conflation.c index 5f6cb730e804..9a69a420a796 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/field_conflation.c +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/field_conflation.c @@ -17,5 +17,5 @@ void test_conflated_fields3(void) { struct XY xy; xy.x = 4; taint_array(&xy); - malloc(xy.x); // not tainted [FALSE POSITIVE] + malloc(xy.x); // not tainted } diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp index cb21e8f1915a..d5d74cdee72c 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp @@ -76,7 +76,7 @@ void processData2(char *start, char *end) { char *copy; - copy = new char[end - start]; // GOOD + copy = new char[end - start]; // GOOD [FALSE POSITIVE] // ... @@ -123,7 +123,7 @@ void open_file_bounded () { int size = atoi(getenv("USER")); int bounded_size = bounded(size, MAX_SIZE); - int* a = (int*)malloc(bounded_size * sizeof(int)); // GOOD + int* a = (int*)malloc(bounded_size * sizeof(int)); // GOOD [FALSE POSITIVE] int* b = (int*)malloc(size * sizeof(int)); // BAD } @@ -229,7 +229,7 @@ void more_cases() { malloc(local_size); // BAD malloc(get_untainted_size()); // GOOD malloc(get_tainted_size()); // BAD - malloc(get_bounded_size()); // GOOD + malloc(get_bounded_size()); // GOOD [FALSE POSITIVE] my_alloc(100); // GOOD my_alloc(local_size); // BAD [NOT DETECTED IN CORRECT LOCATION] From ca2f4c3c0f0f3cc11409d506d3246d63f644b16d Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Tue, 19 May 2020 12:23:35 -0700 Subject: [PATCH 4/9] C++: Add taint test for array-typed fields This adds a copy of the test from before #3511. The prior commit fixed the false positive in the modified version but not the original. --- .../TaintedAllocationSize.expected | 13 ++++++++++++ .../TaintedAllocationSize/field_conflation.c | 21 +++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected index 742a6fae314a..33ef3ec4a080 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected @@ -1,4 +1,10 @@ edges +| field_conflation.c:29:22:29:27 | call to getenv | field_conflation.c:30:10:30:25 | Chi | +| field_conflation.c:30:10:30:25 | Chi | field_conflation.c:36:15:36:17 | taint_array output argument | +| field_conflation.c:36:15:36:17 | taint_array output argument | field_conflation.c:37:10:37:13 | (unsigned long)... | +| field_conflation.c:36:15:36:17 | taint_array output argument | field_conflation.c:37:13:37:13 | x | +| field_conflation.c:36:15:36:17 | taint_array output argument | field_conflation.c:37:13:37:13 | x | +| field_conflation.c:37:13:37:13 | x | field_conflation.c:37:10:37:13 | (unsigned long)... | | test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | (size_t)... | | test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted | | test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... | @@ -36,6 +42,12 @@ edges | test.cpp:235:11:235:20 | (size_t)... | test.cpp:214:23:214:23 | s | | test.cpp:237:10:237:19 | (size_t)... | test.cpp:220:21:220:21 | s | nodes +| field_conflation.c:29:22:29:27 | call to getenv | semmle.label | call to getenv | +| field_conflation.c:30:10:30:25 | Chi | semmle.label | Chi | +| field_conflation.c:36:15:36:17 | taint_array output argument | semmle.label | taint_array output argument | +| field_conflation.c:37:10:37:13 | (unsigned long)... | semmle.label | (unsigned long)... | +| field_conflation.c:37:13:37:13 | x | semmle.label | x | +| field_conflation.c:37:13:37:13 | x | semmle.label | x | | test.cpp:39:21:39:24 | argv | semmle.label | argv | | test.cpp:42:38:42:44 | (size_t)... | semmle.label | (size_t)... | | test.cpp:42:38:42:44 | tainted | semmle.label | tainted | @@ -78,6 +90,7 @@ nodes | test.cpp:235:11:235:20 | (size_t)... | semmle.label | (size_t)... | | test.cpp:237:10:237:19 | (size_t)... | semmle.label | (size_t)... | #select +| field_conflation.c:37:3:37:8 | call to malloc | field_conflation.c:29:22:29:27 | call to getenv | field_conflation.c:37:13:37:13 | x | This allocation size is derived from $@ and might overflow | field_conflation.c:29:22:29:27 | call to getenv | user input (an environment variable) | | test.cpp:42:31:42:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (a command line argument) | | test.cpp:43:31:43:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (a command line argument) | | test.cpp:45:31:45:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:45:38:45:63 | ... + ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (a command line argument) | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/field_conflation.c b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/field_conflation.c index 9a69a420a796..baa0b7837856 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/field_conflation.c +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/field_conflation.c @@ -8,7 +8,7 @@ struct XY { int y; }; -void taint_array(struct XY *xyp) { +void taint_field(struct XY *xyp) { int tainted = atoi(getenv("VAR")); xyp->y = tainted; } @@ -16,6 +16,23 @@ void taint_array(struct XY *xyp) { void test_conflated_fields3(void) { struct XY xy; xy.x = 4; - taint_array(&xy); + taint_field(&xy); malloc(xy.x); // not tainted } + +struct ContainsArray { + int arr[16]; + int x; +}; + +void taint_array(struct ContainsArray *ca, int offset) { + int tainted = atoi(getenv("VAR")); + memcpy(ca->arr + offset, &tainted, sizeof(int)); +} + +void test_conflated_fields4(int arbitrary) { + struct ContainsArray ca; + ca.x = 4; + taint_array(&ca, arbitrary); + malloc(ca.x); // not tainted [FALSE POSITIVE] +} From 9bc95da7a319b8ea87bb331cd6ac4b92ade3d3cd Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 21 May 2020 17:21:41 +0100 Subject: [PATCH 5/9] C++: Autoformat. --- cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql index 4fbac56f51ed..f78bdcb7f19b 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql +++ b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql @@ -42,13 +42,9 @@ class TaintedAllocationSizeConfiguration extends TaintTracking::Configuration { } class UpperBoundGuard extends DataFlow::BarrierGuard { - UpperBoundGuard() { - this.comparesLt(_, _, _, _, _) - } + UpperBoundGuard() { this.comparesLt(_, _, _, _, _) } - override predicate checks(Instruction i, boolean b) { - this.comparesLt(i.getAUse(), _, _, _, b) - } + override predicate checks(Instruction i, boolean b) { this.comparesLt(i.getAUse(), _, _, _, b) } } /* From eb0da11a452f20e6c514360bf58e53075108b20f Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 21 May 2020 17:13:19 +0100 Subject: [PATCH 6/9] C++: Restore hasUpperBoundsCheck. --- .../CWE/CWE-190/TaintedAllocationSize.ql | 47 +++++++++++++++++++ .../TaintedAllocationSize.expected | 17 ------- .../semmle/TaintedAllocationSize/test.cpp | 4 +- 3 files changed, 49 insertions(+), 19 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql index f78bdcb7f19b..379fd859df96 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql +++ b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql @@ -39,6 +39,10 @@ class TaintedAllocationSizeConfiguration extends TaintTracking::Configuration { override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { guard instanceof UpperBoundGuard } + + override predicate isSanitizer(DataFlow::Node node) { + node.asInstruction() instanceof BoundedVariableRead + } } class UpperBoundGuard extends DataFlow::BarrierGuard { @@ -47,6 +51,49 @@ class UpperBoundGuard extends DataFlow::BarrierGuard { override predicate checks(Instruction i, boolean b) { this.comparesLt(i.getAUse(), _, _, _, b) } } +private predicate readsVariable(LoadInstruction load, Variable var) { + load.getSourceAddress().(VariableAddressInstruction).getASTVariable() = var +} + +/** + * A variable that has any kind of upper-bound check anywhere in the program. This is + * biased towards being inclusive because there are a lot of valid ways of doing an + * upper bounds checks if we don't consider where it occurs, for example: + * ``` + * if (x < 10) { sink(x); } + * + * if (10 > y) { sink(y); } + * + * if (z > 10) { z = 10; } + * sink(z); + * ``` + */ +// TODO: This coarse overapproximation, ported from the old taint tracking +// library, could be replaced with an actual semantic check that a particular +// variable _access_ is guarded by an upper-bound check. We probably don't want +// to do this right away since it could expose a lot of FPs that were +// previously suppressed by this predicate by coincidence. +private predicate hasUpperBoundsCheck(Variable var) { + exists(RelationalOperation oper, VariableAccess access | + oper.getAnOperand() = access and + access.getTarget() = var and + // Comparing to 0 is not an upper bound check + not oper.getAnOperand().getValue() = "0" + ) +} + +/** + * A read of a variable that has an upper-bound check somewhere in the + * program. + */ +class BoundedVariableRead extends LoadInstruction { + BoundedVariableRead() { + exists(Variable checkedVar | + readsVariable(this, checkedVar) and + hasUpperBoundsCheck(checkedVar) + ) +} + /* * class TaintedAllocationSizeConfiguration extends TaintTrackingConfiguration { * override predicate isSink(Element tainted) { allocSink(_, tainted) } diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected index 33ef3ec4a080..433fc7912451 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected @@ -23,16 +23,10 @@ edges | test.cpp:100:17:100:22 | processData1 output argument | test.cpp:101:25:101:39 | ... + ... | | test.cpp:101:17:101:22 | array to pointer conversion | test.cpp:75:25:75:29 | start | | test.cpp:101:25:101:39 | ... + ... | test.cpp:75:38:75:40 | end | -| test.cpp:123:18:123:23 | call to getenv | test.cpp:124:29:124:32 | size | | test.cpp:123:18:123:23 | call to getenv | test.cpp:127:24:127:41 | ... * ... | -| test.cpp:124:21:124:27 | call to bounded | test.cpp:126:24:126:49 | ... * ... | -| test.cpp:124:29:124:32 | size | test.cpp:124:21:124:27 | call to bounded | | test.cpp:132:19:132:24 | call to getenv | test.cpp:134:10:134:27 | ... * ... | -| test.cpp:174:19:174:24 | call to getenv | test.cpp:176:10:176:27 | ... * ... | | test.cpp:201:9:201:42 | Store | test.cpp:231:9:231:24 | call to get_tainted_size | | test.cpp:201:14:201:19 | call to getenv | test.cpp:201:9:201:42 | Store | -| test.cpp:206:18:206:23 | call to getenv | test.cpp:211:9:211:9 | Store | -| test.cpp:211:9:211:9 | Store | test.cpp:232:9:232:24 | call to get_bounded_size | | test.cpp:214:23:214:23 | s | test.cpp:215:21:215:21 | s | | test.cpp:220:21:220:21 | s | test.cpp:221:21:221:21 | s | | test.cpp:227:24:227:29 | call to getenv | test.cpp:229:9:229:18 | (size_t)... | @@ -66,18 +60,11 @@ nodes | test.cpp:101:17:101:22 | array to pointer conversion | semmle.label | array to pointer conversion | | test.cpp:101:25:101:39 | ... + ... | semmle.label | ... + ... | | test.cpp:123:18:123:23 | call to getenv | semmle.label | call to getenv | -| test.cpp:124:21:124:27 | call to bounded | semmle.label | call to bounded | -| test.cpp:124:29:124:32 | size | semmle.label | size | -| test.cpp:126:24:126:49 | ... * ... | semmle.label | ... * ... | | test.cpp:127:24:127:41 | ... * ... | semmle.label | ... * ... | | test.cpp:132:19:132:24 | call to getenv | semmle.label | call to getenv | | test.cpp:134:10:134:27 | ... * ... | semmle.label | ... * ... | -| test.cpp:174:19:174:24 | call to getenv | semmle.label | call to getenv | -| test.cpp:176:10:176:27 | ... * ... | semmle.label | ... * ... | | test.cpp:201:9:201:42 | Store | semmle.label | Store | | test.cpp:201:14:201:19 | call to getenv | semmle.label | call to getenv | -| test.cpp:206:18:206:23 | call to getenv | semmle.label | call to getenv | -| test.cpp:211:9:211:9 | Store | semmle.label | Store | | test.cpp:214:23:214:23 | s | semmle.label | s | | test.cpp:215:21:215:21 | s | semmle.label | s | | test.cpp:220:21:220:21 | s | semmle.label | s | @@ -86,7 +73,6 @@ nodes | test.cpp:229:9:229:18 | (size_t)... | semmle.label | (size_t)... | | test.cpp:229:9:229:18 | local_size | semmle.label | local_size | | test.cpp:231:9:231:24 | call to get_tainted_size | semmle.label | call to get_tainted_size | -| test.cpp:232:9:232:24 | call to get_bounded_size | semmle.label | call to get_bounded_size | | test.cpp:235:11:235:20 | (size_t)... | semmle.label | (size_t)... | | test.cpp:237:10:237:19 | (size_t)... | semmle.label | (size_t)... | #select @@ -98,12 +84,9 @@ nodes | test.cpp:49:17:49:30 | new[] | test.cpp:39:21:39:24 | argv | test.cpp:49:26:49:29 | size | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (a command line argument) | | test.cpp:52:21:52:27 | call to realloc | test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (a command line argument) | | test.cpp:79:9:79:29 | new[] | test.cpp:97:18:97:23 | fread output argument | test.cpp:79:18:79:28 | ... - ... | This allocation size is derived from $@ and might overflow | test.cpp:97:18:97:23 | buffer | user input (String read by fread) | -| test.cpp:126:17:126:22 | call to malloc | test.cpp:123:18:123:23 | call to getenv | test.cpp:126:24:126:49 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:123:18:123:23 | call to getenv | user input (an environment variable) | | test.cpp:127:17:127:22 | call to malloc | test.cpp:123:18:123:23 | call to getenv | test.cpp:127:24:127:41 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:123:18:123:23 | call to getenv | user input (an environment variable) | | test.cpp:134:3:134:8 | call to malloc | test.cpp:132:19:132:24 | call to getenv | test.cpp:134:10:134:27 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:132:19:132:24 | call to getenv | user input (an environment variable) | -| test.cpp:176:3:176:8 | call to malloc | test.cpp:174:19:174:24 | call to getenv | test.cpp:176:10:176:27 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:174:19:174:24 | call to getenv | user input (an environment variable) | | test.cpp:215:14:215:19 | call to malloc | test.cpp:227:24:227:29 | call to getenv | test.cpp:215:21:215:21 | s | This allocation size is derived from $@ and might overflow | test.cpp:227:24:227:29 | call to getenv | user input (an environment variable) | | test.cpp:221:14:221:19 | call to malloc | test.cpp:227:24:227:29 | call to getenv | test.cpp:221:21:221:21 | s | This allocation size is derived from $@ and might overflow | test.cpp:227:24:227:29 | call to getenv | user input (an environment variable) | | test.cpp:229:2:229:7 | call to malloc | test.cpp:227:24:227:29 | call to getenv | test.cpp:229:9:229:18 | local_size | This allocation size is derived from $@ and might overflow | test.cpp:227:24:227:29 | call to getenv | user input (an environment variable) | | test.cpp:231:2:231:7 | call to malloc | test.cpp:201:14:201:19 | call to getenv | test.cpp:231:9:231:24 | call to get_tainted_size | This allocation size is derived from $@ and might overflow | test.cpp:201:14:201:19 | call to getenv | user input (an environment variable) | -| test.cpp:232:2:232:7 | call to malloc | test.cpp:206:18:206:23 | call to getenv | test.cpp:232:9:232:24 | call to get_bounded_size | This allocation size is derived from $@ and might overflow | test.cpp:206:18:206:23 | call to getenv | user input (an environment variable) | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp index d5d74cdee72c..86a4ab47de88 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp @@ -123,7 +123,7 @@ void open_file_bounded () { int size = atoi(getenv("USER")); int bounded_size = bounded(size, MAX_SIZE); - int* a = (int*)malloc(bounded_size * sizeof(int)); // GOOD [FALSE POSITIVE] + int* a = (int*)malloc(bounded_size * sizeof(int)); // GOOD int* b = (int*)malloc(size * sizeof(int)); // BAD } @@ -229,7 +229,7 @@ void more_cases() { malloc(local_size); // BAD malloc(get_untainted_size()); // GOOD malloc(get_tainted_size()); // BAD - malloc(get_bounded_size()); // GOOD [FALSE POSITIVE] + malloc(get_bounded_size()); // GOOD my_alloc(100); // GOOD my_alloc(local_size); // BAD [NOT DETECTED IN CORRECT LOCATION] From 78a4e0dd3171acb41b757259f6a945ed1044a90c Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Wed, 27 May 2020 14:43:25 -0700 Subject: [PATCH 7/9] C++: delete commented out code --- cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql index 379fd859df96..c0578e6d04cf 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql +++ b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql @@ -92,14 +92,9 @@ class BoundedVariableRead extends LoadInstruction { readsVariable(this, checkedVar) and hasUpperBoundsCheck(checkedVar) ) + } } -/* - * class TaintedAllocationSizeConfiguration extends TaintTrackingConfiguration { - * override predicate isSink(Element tainted) { allocSink(_, tainted) } - * } - */ - predicate taintedAllocSize( Expr source, Expr alloc, DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode, string taintCause From 249e67ff99a2625c72b8a624d6f0b9664e424e6b Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 28 May 2020 10:23:10 -0700 Subject: [PATCH 8/9] C++: Add EqualityGuard in TaintedAllocationSize.ql --- .../src/Security/CWE/CWE-190/TaintedAllocationSize.ql | 10 ++++++++++ .../TaintedAllocationSize.expected | 7 ------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql index c0578e6d04cf..72aba4ec947b 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql +++ b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql @@ -14,6 +14,8 @@ import cpp import semmle.code.cpp.ir.dataflow.TaintTracking import semmle.code.cpp.security.FlowSources +import semmle.code.cpp.controlflow.IRGuards +import semmle.code.cpp.ir.ValueNumbering import DataFlow::PathGraph import semmle.code.cpp.ir.IR @@ -38,6 +40,8 @@ class TaintedAllocationSizeConfiguration extends TaintTracking::Configuration { override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { guard instanceof UpperBoundGuard + or + guard instanceof EqualityGuard } override predicate isSanitizer(DataFlow::Node node) { @@ -51,6 +55,12 @@ class UpperBoundGuard extends DataFlow::BarrierGuard { override predicate checks(Instruction i, boolean b) { this.comparesLt(i.getAUse(), _, _, _, b) } } +class EqualityGuard extends DataFlow::BarrierGuard { + EqualityGuard() { this.comparesEq(_, _, _, _, _) } + + override predicate checks(Instruction i, boolean b) { this.comparesEq(i.getAUse(), _, _, true, b) } +} + private predicate readsVariable(LoadInstruction load, Variable var) { load.getSourceAddress().(VariableAddressInstruction).getASTVariable() = var } diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected index e6bab27984ca..40a4994a03ee 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected @@ -36,8 +36,6 @@ edges | test.cpp:235:11:235:20 | (size_t)... | test.cpp:214:23:214:23 | s | | test.cpp:237:10:237:19 | (size_t)... | test.cpp:220:21:220:21 | s | | test.cpp:249:20:249:25 | call to getenv | test.cpp:253:11:253:29 | ... * ... | -| test.cpp:249:20:249:25 | call to getenv | test.cpp:257:11:257:29 | ... * ... | -| test.cpp:261:19:261:24 | call to getenv | test.cpp:266:10:266:27 | ... * ... | | test.cpp:301:19:301:24 | call to getenv | test.cpp:305:11:305:28 | ... * ... | | test.cpp:309:19:309:24 | call to getenv | test.cpp:314:10:314:27 | ... * ... | nodes @@ -82,9 +80,6 @@ nodes | test.cpp:237:10:237:19 | (size_t)... | semmle.label | (size_t)... | | test.cpp:249:20:249:25 | call to getenv | semmle.label | call to getenv | | test.cpp:253:11:253:29 | ... * ... | semmle.label | ... * ... | -| test.cpp:257:11:257:29 | ... * ... | semmle.label | ... * ... | -| test.cpp:261:19:261:24 | call to getenv | semmle.label | call to getenv | -| test.cpp:266:10:266:27 | ... * ... | semmle.label | ... * ... | | test.cpp:301:19:301:24 | call to getenv | semmle.label | call to getenv | | test.cpp:305:11:305:28 | ... * ... | semmle.label | ... * ... | | test.cpp:309:19:309:24 | call to getenv | semmle.label | call to getenv | @@ -105,7 +100,5 @@ nodes | test.cpp:229:2:229:7 | call to malloc | test.cpp:227:24:227:29 | call to getenv | test.cpp:229:9:229:18 | local_size | This allocation size is derived from $@ and might overflow | test.cpp:227:24:227:29 | call to getenv | user input (an environment variable) | | test.cpp:231:2:231:7 | call to malloc | test.cpp:201:14:201:19 | call to getenv | test.cpp:231:9:231:24 | call to get_tainted_size | This allocation size is derived from $@ and might overflow | test.cpp:201:14:201:19 | call to getenv | user input (an environment variable) | | test.cpp:253:4:253:9 | call to malloc | test.cpp:249:20:249:25 | call to getenv | test.cpp:253:11:253:29 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:249:20:249:25 | call to getenv | user input (an environment variable) | -| test.cpp:257:4:257:9 | call to malloc | test.cpp:249:20:249:25 | call to getenv | test.cpp:257:11:257:29 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:249:20:249:25 | call to getenv | user input (an environment variable) | -| test.cpp:266:3:266:8 | call to malloc | test.cpp:261:19:261:24 | call to getenv | test.cpp:266:10:266:27 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:261:19:261:24 | call to getenv | user input (an environment variable) | | test.cpp:305:4:305:9 | call to malloc | test.cpp:301:19:301:24 | call to getenv | test.cpp:305:11:305:28 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:301:19:301:24 | call to getenv | user input (an environment variable) | | test.cpp:314:3:314:8 | call to malloc | test.cpp:309:19:309:24 | call to getenv | test.cpp:314:10:314:27 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:309:19:309:24 | call to getenv | user input (an environment variable) | From 304b8cc34a27d472460474797944fa28db87f594 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 1 Jun 2020 11:06:39 -0700 Subject: [PATCH 9/9] C++: autoformat --- cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql index 72aba4ec947b..59a93c9f1b2c 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql +++ b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql @@ -58,7 +58,9 @@ class UpperBoundGuard extends DataFlow::BarrierGuard { class EqualityGuard extends DataFlow::BarrierGuard { EqualityGuard() { this.comparesEq(_, _, _, _, _) } - override predicate checks(Instruction i, boolean b) { this.comparesEq(i.getAUse(), _, _, true, b) } + override predicate checks(Instruction i, boolean b) { + this.comparesEq(i.getAUse(), _, _, true, b) + } } private predicate readsVariable(LoadInstruction load, Variable var) {