mirror of
https://github.com/github/codeql.git
synced 2026-04-27 01:35:13 +02:00
C++: Port dataflow/dataflow-tests to inline expectations test library.
This commit is contained in:
@@ -6,13 +6,13 @@ void bg_basic(int source) {
|
||||
if (guarded(source)) {
|
||||
sink(source); // no flow
|
||||
} else {
|
||||
sink(source); // flow
|
||||
sink(source); // $ ast,ir
|
||||
}
|
||||
}
|
||||
|
||||
void bg_not(int source) {
|
||||
if (!guarded(source)) {
|
||||
sink(source); // flow
|
||||
sink(source); // $ ast,ir
|
||||
} else {
|
||||
sink(source); // no flow
|
||||
}
|
||||
@@ -22,15 +22,15 @@ void bg_and(int source, bool arbitrary) {
|
||||
if (guarded(source) && arbitrary) {
|
||||
sink(source); // no flow
|
||||
} else {
|
||||
sink(source); // flow
|
||||
sink(source); // $ ast,ir
|
||||
}
|
||||
}
|
||||
|
||||
void bg_or(int source, bool arbitrary) {
|
||||
if (guarded(source) || arbitrary) {
|
||||
sink(source); // flow
|
||||
sink(source); // $ ast,ir
|
||||
} else {
|
||||
sink(source); // flow
|
||||
sink(source); // $ ast,ir
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,21 +48,21 @@ struct XY {
|
||||
void bg_stackstruct(XY s1, XY s2) {
|
||||
s1.x = source();
|
||||
if (guarded(s1.x)) {
|
||||
sink(s1.x); // no flow [FALSE POSITIVE in AST]
|
||||
sink(s1.x); // $ SPURIOUS: ast
|
||||
} else if (guarded(s1.y)) {
|
||||
sink(s1.x); // flow
|
||||
sink(s1.x); // $ ast,ir
|
||||
} else if (guarded(s2.y)) {
|
||||
sink(s1.x); // flow
|
||||
sink(s1.x); // $ ast,ir
|
||||
}
|
||||
}
|
||||
|
||||
void bg_structptr(XY *p1, XY *p2) {
|
||||
p1->x = source();
|
||||
if (guarded(p1->x)) {
|
||||
sink(p1->x); // no flow [FALSE POSITIVE in AST]
|
||||
sink(p1->x); // $ SPURIOUS: ast
|
||||
} else if (guarded(p1->y)) {
|
||||
sink(p1->x); // flow
|
||||
sink(p1->x); // $ ast,ir
|
||||
} else if (guarded(p2->x)) {
|
||||
sink(p1->x); // flow
|
||||
sink(p1->x); // $ ast,ir
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.DataFlow
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
|
||||
/**
|
||||
* A `BarrierGuard` that stops flow to all occurrences of `x` within statement
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.ir.dataflow.DataFlow
|
||||
import semmle.code.cpp.ir.IR
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
|
||||
/**
|
||||
* A `BarrierGuard` that stops flow to all occurrences of `x` within statement
|
||||
@@ -24,9 +25,6 @@ class TestAllocationConfig extends DataFlow::Configuration {
|
||||
source.asExpr().(FunctionCall).getTarget().getName() = "source"
|
||||
or
|
||||
source.asParameter().getName().matches("source%")
|
||||
or
|
||||
// Track uninitialized variables
|
||||
exists(source.asUninitialized())
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
|
||||
@@ -9,7 +9,7 @@ void sink(int);
|
||||
// this result and be forced to write a better test if the function signature
|
||||
// detection should improve.
|
||||
void calleeAcrossLinkTargets(long x) {
|
||||
sink(x);
|
||||
sink(x); // $ ast,ir
|
||||
}
|
||||
|
||||
void calleeAcrossLinkTargets(int x); // no body
|
||||
|
||||
@@ -15,39 +15,38 @@ void following_pointers(
|
||||
twoIntFields *sourceStruct1_ptr,
|
||||
int (*sourceFunctionPointer)())
|
||||
{
|
||||
sink(sourceArray1); // flow
|
||||
sink(sourceArray1); // $ ast,ir
|
||||
|
||||
sink(sourceArray1[0]); // no flow
|
||||
sink(*sourceArray1); // no flow
|
||||
sink(&sourceArray1); // flow (should probably be taint only)
|
||||
sink(&sourceArray1); // $ ast // [should probably taint only]
|
||||
|
||||
sink(sourceStruct1.m1); // no flow
|
||||
sink(sourceStruct1_ptr->m1); // no flow
|
||||
sink(sourceStruct1_ptr->getFirst()); // no flow
|
||||
|
||||
sourceStruct1_ptr->m1 = source();
|
||||
sink(sourceStruct1_ptr->m1); // flow
|
||||
sink(sourceStruct1_ptr->getFirst()); // flow
|
||||
sink(sourceStruct1_ptr->m1); // $ ast,ir
|
||||
sink(sourceStruct1_ptr->getFirst()); // $ ast,ir
|
||||
sink(sourceStruct1_ptr->m2); // no flow
|
||||
sink(sourceStruct1.m1); // no flow
|
||||
|
||||
twoIntFields s = { source(), source() };
|
||||
|
||||
|
||||
sink(s.m2); // flow
|
||||
sink(s.m2); // $ ast,ir
|
||||
|
||||
twoIntFields sArray[1] = { { source(), source() } };
|
||||
// TODO: fix this like above
|
||||
sink(sArray[0].m2); // flow (AST dataflow misses this due to limitations of the analysis)
|
||||
sink(sArray[0].m2); // $ ir MISSING: ast
|
||||
|
||||
twoIntFields sSwapped = { .m2 = source(), .m1 = 0 };
|
||||
|
||||
sink(sSwapped.m2); // flow
|
||||
sink(sSwapped.m2); // $ ast,ir
|
||||
|
||||
sink(sourceFunctionPointer()); // no flow
|
||||
|
||||
int stackArray[2] = { source(), source() };
|
||||
stackArray[0] = source();
|
||||
sink(stackArray); // flow
|
||||
sink(stackArray); // $ ast MISSING: ir
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ struct Top {
|
||||
virtual void isSink(int x) { }
|
||||
virtual int notSource1() { return source(); }
|
||||
virtual int notSource2() { return source(); }
|
||||
virtual void notSink(int x) { sink(x); }
|
||||
virtual void notSink(int x) { sink(x); } // $ SPURIOUS: ast,ir=37:19 ast,ir=45:18
|
||||
};
|
||||
|
||||
// This class has the correct behavior for just the functions ending in 2.
|
||||
@@ -20,7 +20,7 @@ struct Middle : Top {
|
||||
// This class has all the behavior suggested by the function names.
|
||||
struct Bottom : Middle {
|
||||
int isSource1() override { return source(); }
|
||||
void isSink(int x) override { sink(x); }
|
||||
void isSink(int x) override { sink(x); } // $ ir=33:18 ir=41:17 ir=69:15 ir=73:14 ir=81:13 MISSING: ast=33:18 ast=41:17 ast=69:15 ast=73:14 ast=81:13
|
||||
int notSource1() override { return 0; }
|
||||
void notSink(int x) override { }
|
||||
};
|
||||
@@ -28,21 +28,21 @@ struct Bottom : Middle {
|
||||
void VirtualDispatch(Bottom *bottomPtr, Bottom &bottomRef) {
|
||||
Top *topPtr = bottomPtr, &topRef = bottomRef;
|
||||
|
||||
sink(topPtr->isSource1()); // flow [NOT DETECTED by AST]
|
||||
sink(topPtr->isSource2()); // flow [NOT DETECTED by AST]
|
||||
topPtr->isSink(source()); // flow [NOT DETECTED by AST]
|
||||
sink(topPtr->isSource1()); // $ ir MISSING: ast
|
||||
sink(topPtr->isSource2()); // $ ir MISSING: ast
|
||||
topPtr->isSink(source()); // causing a MISSING for ast
|
||||
|
||||
sink(topPtr->notSource1()); // no flow [FALSE POSITIVE]
|
||||
sink(topPtr->notSource2()); // no flow [FALSE POSITIVE]
|
||||
topPtr->notSink(source()); // no flow [FALSE POSITIVE]
|
||||
sink(topPtr->notSource1()); // $ SPURIOUS: ast,ir
|
||||
sink(topPtr->notSource2()); // $ SPURIOUS: ast,ir
|
||||
topPtr->notSink(source()); // causing SPURIOUS for ast,ir
|
||||
|
||||
sink(topRef.isSource1()); // flow [NOT DETECTED by AST]
|
||||
sink(topRef.isSource2()); // flow [NOT DETECTED by AST]
|
||||
topRef.isSink(source()); // flow [NOT DETECTED by AST]
|
||||
sink(topRef.isSource1()); // $ ir MISSING: ast
|
||||
sink(topRef.isSource2()); // $ ir MISSING: ast
|
||||
topRef.isSink(source()); // causing a MISSING for ast
|
||||
|
||||
sink(topRef.notSource1()); // no flow [FALSE POSITIVE]
|
||||
sink(topRef.notSource2()); // no flow [FALSE POSITIVE]
|
||||
topRef.notSink(source()); // no flow [FALSE POSITIVE]
|
||||
sink(topRef.notSource1()); // $ SPURIOUS: ast,ir
|
||||
sink(topRef.notSource2()); // $ SPURIOUS: ast,ir
|
||||
topRef.notSink(source()); // causing SPURIOUS for ast,ir
|
||||
}
|
||||
|
||||
Top *globalBottom, *globalMiddle;
|
||||
@@ -52,10 +52,10 @@ Top *readGlobalBottom() {
|
||||
}
|
||||
|
||||
void DispatchThroughGlobal() {
|
||||
sink(globalBottom->isSource1()); // flow [NOT DETECTED by AST]
|
||||
sink(globalBottom->isSource1()); // $ ir MISSING: ast
|
||||
sink(globalMiddle->isSource1()); // no flow
|
||||
|
||||
sink(readGlobalBottom()->isSource1()); // flow [NOT DETECTED by AST]
|
||||
sink(readGlobalBottom()->isSource1()); // $ ir MISSING: ast
|
||||
|
||||
globalBottom = new Bottom();
|
||||
globalMiddle = new Middle();
|
||||
@@ -66,11 +66,11 @@ Top *allocateBottom() {
|
||||
}
|
||||
|
||||
void callSinkByPointer(Top *top) {
|
||||
top->isSink(source()); // flow [NOT DETECTED by AST]
|
||||
top->isSink(source()); // leads to MISSING from ast
|
||||
}
|
||||
|
||||
void callSinkByReference(Top &top) {
|
||||
top.isSink(source()); // flow [NOT DETECTED by AST]
|
||||
top.isSink(source()); // leads to MISSING from ast
|
||||
}
|
||||
|
||||
void globalVirtualDispatch() {
|
||||
@@ -78,7 +78,7 @@ void globalVirtualDispatch() {
|
||||
callSinkByReference(*allocateBottom());
|
||||
|
||||
Top *x = allocateBottom();
|
||||
x->isSink(source()); // flow [NOT DETECTED by AST]
|
||||
x->isSink(source()); // $ MISSING: ast,ir
|
||||
}
|
||||
|
||||
Top *identity(Top *top) {
|
||||
@@ -86,14 +86,14 @@ Top *identity(Top *top) {
|
||||
}
|
||||
|
||||
void callIdentityFunctions(Top *top, Bottom *bottom) {
|
||||
identity(bottom)->isSink(source()); // flow [NOT DETECTED]
|
||||
identity(bottom)->isSink(source()); // $ MISSING: ast,ir
|
||||
identity(top)->isSink(source()); // now flow
|
||||
}
|
||||
|
||||
using SinkFunctionType = void (*)(int);
|
||||
|
||||
void callSink(int x) {
|
||||
sink(x);
|
||||
sink(x); // $ ir=107:17 ir=140:8 ir=144:8 MISSING: ast=107:17 ast=140:8 ast=144:8
|
||||
}
|
||||
|
||||
SinkFunctionType returnCallSink() {
|
||||
@@ -104,7 +104,7 @@ void testFunctionPointer(SinkFunctionType maybeCallSink, SinkFunctionType dontCa
|
||||
if (b) {
|
||||
maybeCallSink = returnCallSink();
|
||||
}
|
||||
maybeCallSink(source()); // flow [NOT DETECTED by AST]
|
||||
maybeCallSink(source());
|
||||
dontCallSink(source()); // no flow
|
||||
}
|
||||
|
||||
@@ -126,8 +126,8 @@ namespace virtual_inheritance {
|
||||
// get flow from a `Middle` value to the call qualifier.
|
||||
Top *topPtr = bottomPtr, &topRef = bottomRef;
|
||||
|
||||
sink(topPtr->isSource()); // flow [NOT DETECTED]
|
||||
sink(topRef.isSource()); // flow [NOT DETECTED]
|
||||
sink(topPtr->isSource()); // $ MISSING: ast,ir
|
||||
sink(topRef.isSource()); // $ MISSING: ast,ir
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,6 +170,6 @@ void set_global_union_field_u_f() {
|
||||
|
||||
void test_call_sink_through_union_2() {
|
||||
set_global_union_field_u_f();
|
||||
call_sink_through_union_field_u_f(u2.u.f); // flow [NOT DETECTED]
|
||||
call_sink_through_union_field_u_g(u2.u.g); // flow [NOT DETECTED]
|
||||
call_sink_through_union_field_u_f(u2.u.f); // $ MISSING: ast,ir
|
||||
call_sink_through_union_field_u_g(u2.u.g); // $ MISSING: ast,ir
|
||||
}
|
||||
@@ -3,20 +3,20 @@ void sink(int);
|
||||
|
||||
void throughLocal() {
|
||||
int local = source();
|
||||
sink(local); // flow
|
||||
sink(local); // $ ast,ir
|
||||
}
|
||||
|
||||
int flowTestGlobal1 = 0;
|
||||
|
||||
void readWriteGlobal1() {
|
||||
sink(flowTestGlobal1); // flow
|
||||
sink(flowTestGlobal1); // $ ir MISSING: ast
|
||||
flowTestGlobal1 = source();
|
||||
}
|
||||
|
||||
static int flowTestGlobal2 = 0;
|
||||
|
||||
void readGlobal2() {
|
||||
sink(flowTestGlobal2); // flow
|
||||
sink(flowTestGlobal2); // $ ir MISSING: ast
|
||||
}
|
||||
|
||||
void writeGlobal2() {
|
||||
|
||||
@@ -11,37 +11,37 @@ void test_lambdas()
|
||||
int w = 0;
|
||||
|
||||
auto a = [t, u]() -> int {
|
||||
sink(t); // flow from source()
|
||||
sink(t); // $ ast,ir
|
||||
sink(u);
|
||||
return t;
|
||||
};
|
||||
sink(a()); // flow from source()
|
||||
sink(a()); // $ ast,ir
|
||||
|
||||
auto b = [&] {
|
||||
sink(t); // flow from source()
|
||||
sink(t); // $ ast MISSING: ir
|
||||
sink(u);
|
||||
v = source(); // (v is reference captured)
|
||||
};
|
||||
b();
|
||||
sink(v); // flow from source() [NOT DETECTED]
|
||||
sink(v); // $ MISSING: ast,ir
|
||||
|
||||
auto c = [=] {
|
||||
sink(t); // flow from source()
|
||||
sink(t); // $ ast,ir
|
||||
sink(u);
|
||||
};
|
||||
c();
|
||||
|
||||
auto d = [](int a, int b) {
|
||||
sink(a); // flow from source()
|
||||
sink(a); // $ ast,ir
|
||||
sink(b);
|
||||
};
|
||||
d(t, u);
|
||||
|
||||
auto e = [](int &a, int &b, int &c) {
|
||||
sink(a); // flow from source()
|
||||
sink(a); // $ ast,ir
|
||||
sink(b);
|
||||
c = source();
|
||||
};
|
||||
e(t, u, w);
|
||||
sink(w); // flow from source()
|
||||
sink(w); // $ ast,ir
|
||||
}
|
||||
|
||||
@@ -53,16 +53,16 @@ namespace withoutFields {
|
||||
int x1, x2, x3, x4;
|
||||
|
||||
assignWrapper(x1, source());
|
||||
sink(x1); // flow [FALSE POSITIVE from uninitialized]
|
||||
sink(x1); // $ ast=55:23 ir SPURIOUS: ast=53:9
|
||||
|
||||
notAssign(x2, source());
|
||||
sink(x2); // no flow [FALSE POSITIVE from uninitialized, FALSE POSITIVE by IR]
|
||||
sink(x2); // $ SPURIOUS: ast,ir
|
||||
|
||||
sourceToParamWrapper(x3);
|
||||
sink(x3); // flow [FALSE POSITIVE from uninitialized]
|
||||
sink(x3); // $ ast=29:11 ir SPURIOUS: ast=53:17
|
||||
|
||||
notSource(x4);
|
||||
sink(x4); // no flow [FALSE POSITIVE from uninitialized, FALSE POSITIVE by IR]
|
||||
sink(x4); // $ SPURIOUS: ast,ir
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,15 +120,15 @@ namespace withFields {
|
||||
Int x1, x2, x3, x4;
|
||||
|
||||
assignWrapper(x1, source());
|
||||
sink(x1.val); // flow
|
||||
sink(x1.val); // $ ast,ir
|
||||
|
||||
notAssign(x2, source());
|
||||
sink(x2.val); // no flow [FALSE POSITIVE]
|
||||
sink(x2.val); // $ SPURIOUS: ast,ir
|
||||
|
||||
sourceToParamWrapper(x3);
|
||||
sink(x3.val); // flow
|
||||
sink(x3.val); // $ ast,ir
|
||||
|
||||
notSource(x4);
|
||||
sink(x4.val); // no flow [FALSE POSITIVE]
|
||||
sink(x4.val); // $ SPURIOUS: ast,ir
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,15 +4,15 @@ void sink(int); void sink(const int *); void sink(int **);
|
||||
void intraprocedural_with_local_flow() {
|
||||
int t2;
|
||||
int t1 = source();
|
||||
sink(t1); // tainted
|
||||
sink(t1); // $ ast,ir
|
||||
t2 = t1;
|
||||
sink(t1); // tainted
|
||||
sink(t2); // tainted
|
||||
sink(t1); // $ ast,ir
|
||||
sink(t2); // $ ast,ir
|
||||
if (t1) {
|
||||
t2 = 0;
|
||||
sink(t2); // clean
|
||||
}
|
||||
sink(t2); // tainted
|
||||
sink(t2); // $ ast,ir
|
||||
|
||||
t1 = 0;
|
||||
while (false) {
|
||||
@@ -23,12 +23,12 @@ void intraprocedural_with_local_flow() {
|
||||
for (int i = 0; i < t1; i++) {
|
||||
t1 = t2;
|
||||
}
|
||||
sink(t1); // tainted
|
||||
sink(t1); // $ ast,ir
|
||||
}
|
||||
|
||||
static void callee(int t, int c) {
|
||||
sink(t); // tainted (from first call in caller() function)
|
||||
sink(c); // tainted (from second call in caller() function)
|
||||
sink(t); // $ ast,ir // (from first call in caller() function)
|
||||
sink(c); // $ ast,ir // (from second call in caller() function)
|
||||
}
|
||||
|
||||
void caller() {
|
||||
@@ -55,7 +55,7 @@ void branching(bool b) {
|
||||
}
|
||||
|
||||
|
||||
sink(t); // tainted
|
||||
sink(t); // $ ast,ir
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,12 +68,12 @@ void identityOperations(int* source1) {
|
||||
int* x2 = const_cast<int*>(x1);
|
||||
int* x3 = (x2);
|
||||
const int* x4 = (const int *)x3;
|
||||
sink(x4);
|
||||
sink(x4); // $ ast,ir
|
||||
}
|
||||
|
||||
void trackUninitialized() {
|
||||
void trackUninitialized() { // NOTE: uninitialized tracking for IR dataflow is deprecated
|
||||
int u1;
|
||||
sink(u1); // tainted
|
||||
sink(u1); // $ ast
|
||||
u1 = 2;
|
||||
sink(u1); // clean
|
||||
|
||||
@@ -81,15 +81,15 @@ void trackUninitialized() {
|
||||
sink(i1); // clean
|
||||
|
||||
int u2;
|
||||
sink(i1 ? u2 : 1); // tainted
|
||||
sink(i1 ? u2 : 1); // $ ast
|
||||
i1 = u2;
|
||||
sink(i1); // tainted
|
||||
sink(i1); // $ ast
|
||||
}
|
||||
|
||||
void local_references(int &source1, int clean1) {
|
||||
sink(source1); // tainted
|
||||
sink(source1); // $ ast,ir
|
||||
source1 = clean1;
|
||||
sink(source1); // clean
|
||||
sink(source1); // $ SPURIOUS: ir
|
||||
|
||||
// The next two test cases show that the analysis does not understand the "&"
|
||||
// on the type at all. It does not understand that the initialization creates
|
||||
@@ -100,14 +100,14 @@ void local_references(int &source1, int clean1) {
|
||||
int t = source();
|
||||
int &ref = t;
|
||||
t = clean1;
|
||||
sink(ref); // clean (FALSE POSITIVE)
|
||||
sink(ref); // $ SPURIOUS: ast
|
||||
}
|
||||
|
||||
{
|
||||
int t = clean1;
|
||||
int &ref = t;
|
||||
t = source();
|
||||
sink(ref); // tainted (FALSE NEGATIVE)
|
||||
sink(ref); // $ ir MISSING: ast
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,11 +137,11 @@ int returnParameter(int p) {
|
||||
void callReturnParameter() {
|
||||
int x = returnParameter(source());
|
||||
int y = x;
|
||||
sink(y); // tainted due to above source
|
||||
sink(y); // $ ast,ir
|
||||
}
|
||||
|
||||
int returnSourceParameter(int s) {
|
||||
sink(s); // tainted
|
||||
sink(s); // $ ast,ir // from line 151
|
||||
return s; // considered clean unless the caller passes taint into the parameter source
|
||||
}
|
||||
|
||||
@@ -149,12 +149,12 @@ void callReturnSourceParameter() {
|
||||
int x = returnSourceParameter(0);
|
||||
sink(x); // clean
|
||||
int y = returnSourceParameter(source());
|
||||
sink(y); // tainted
|
||||
sink(y); // $ ast,ir
|
||||
}
|
||||
|
||||
int returnSourceParameter2(int s) {
|
||||
int x = s;
|
||||
sink(x); // tainted
|
||||
sink(x); // $ ast,ir // from line 164
|
||||
return x; // considered clean unless the caller passes taint into the parameter source
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ void callReturnSourceParameter2() {
|
||||
int x = returnSourceParameter2(0);
|
||||
sink(x); // clean
|
||||
int y = returnSourceParameter2(source());
|
||||
sink(y); // tainted
|
||||
sink(y); // $ ast,ir
|
||||
}
|
||||
|
||||
// Tests for non-parameter sources returned to a function call
|
||||
@@ -175,7 +175,7 @@ int returnSource() {
|
||||
void callReturnSource() {
|
||||
int x = returnSource();
|
||||
int y = x;
|
||||
sink(y); // tainted
|
||||
sink(y); // $ ast,ir
|
||||
}
|
||||
|
||||
// TESTS WITH BARRIERS: none of these should have results
|
||||
@@ -257,13 +257,13 @@ namespace NestedTests {
|
||||
}
|
||||
|
||||
void level2(int x) {
|
||||
sink(x); // tainted from call to level1() but not from call to safelevel1()
|
||||
sink(x); // $ ast,ir // tainted from call to level1() but not from call to safelevel1()
|
||||
}
|
||||
};
|
||||
class FlowThroughFunctionReturn {
|
||||
void level0() {
|
||||
int x = level1(source());
|
||||
sink(x); // tainted
|
||||
sink(x); // $ ast,ir
|
||||
x = safelevel1(source());
|
||||
sink(x); // no longer tainted
|
||||
}
|
||||
@@ -286,7 +286,7 @@ namespace NestedTests {
|
||||
class FlowOutOfFunction {
|
||||
void level0() {
|
||||
int x = level1();
|
||||
sink(x); // tainted
|
||||
sink(x); // $ ast,ir
|
||||
x = safelevel1();
|
||||
sink(x); // no longer tainted
|
||||
}
|
||||
@@ -315,7 +315,7 @@ namespace NestedTests {
|
||||
}
|
||||
void g(int p) {
|
||||
int x = h(p);
|
||||
sink(x); // tainted from f
|
||||
sink(x); // $ ast,ir // tainted from f
|
||||
int y = h(0);
|
||||
sink(y); // clean
|
||||
f();
|
||||
@@ -336,17 +336,17 @@ namespace FlowThroughGlobals {
|
||||
int f() {
|
||||
sink(globalVar); // tainted or clean? Not sure.
|
||||
taintGlobal();
|
||||
sink(globalVar); // tainted (FALSE NEGATIVE)
|
||||
sink(globalVar); // $ MISSING: ast,ir
|
||||
}
|
||||
|
||||
int calledAfterTaint() {
|
||||
sink(globalVar); // tainted (FALSE NEGATIVE)
|
||||
sink(globalVar); // $ MISSING: ast,ir
|
||||
}
|
||||
|
||||
int taintAndCall() {
|
||||
globalVar = source();
|
||||
calledAfterTaint();
|
||||
sink(globalVar); // tainted
|
||||
sink(globalVar); // $ ast MISSING: ir
|
||||
}
|
||||
}
|
||||
|
||||
@@ -362,17 +362,17 @@ class FlowThroughFields {
|
||||
int f() {
|
||||
sink(field); // tainted or clean? Not sure.
|
||||
taintField();
|
||||
sink(field); // tainted [NOT DETECTED with IR]
|
||||
sink(field); // $ ast MISSING: ir
|
||||
}
|
||||
|
||||
int calledAfterTaint() {
|
||||
sink(field); // tainted
|
||||
sink(field); // $ ast,ir
|
||||
}
|
||||
|
||||
int taintAndCall() {
|
||||
field = source();
|
||||
calledAfterTaint();
|
||||
sink(field); // tainted
|
||||
sink(field); // $ ast,ir
|
||||
}
|
||||
};
|
||||
|
||||
@@ -382,30 +382,30 @@ void *memcpy(void *dest, const void *src, size_t count);
|
||||
void flowThroughMemcpy_ssa_with_local_flow(int source1) {
|
||||
int tmp = 0;
|
||||
memcpy(&tmp, &source1, sizeof tmp);
|
||||
sink(tmp); // tainted
|
||||
sink(tmp); // $ ast,ir
|
||||
}
|
||||
|
||||
void flowThroughMemcpy_blockvar_with_local_flow(int source1, int b) {
|
||||
int tmp = 0;
|
||||
int *capture = &tmp;
|
||||
memcpy(&tmp, &source1, sizeof tmp);
|
||||
sink(tmp); // tainted
|
||||
sink(tmp); // $ ast,ir
|
||||
if (b) {
|
||||
sink(tmp); // tainted
|
||||
sink(tmp); // $ ast,ir
|
||||
}
|
||||
}
|
||||
|
||||
void cleanedByMemcpy_ssa(int clean1) { // currently modeled with BlockVar, not SSA
|
||||
int tmp;
|
||||
memcpy(&tmp, &clean1, sizeof tmp);
|
||||
sink(tmp); // clean [FALSE POSITIVE]
|
||||
sink(tmp); // $ SPURIOUS: ast
|
||||
}
|
||||
|
||||
void cleanedByMemcpy_blockvar(int clean1) {
|
||||
int tmp;
|
||||
int *capture = &tmp;
|
||||
memcpy(&tmp, &clean1, sizeof tmp);
|
||||
sink(tmp); // clean [FALSE POSITIVE]
|
||||
sink(tmp); // $ SPURIOUS: ast
|
||||
}
|
||||
|
||||
void intRefSource(int &ref_source);
|
||||
@@ -415,39 +415,39 @@ void intArraySource(int ref_source[], size_t len);
|
||||
void intRefSourceCaller() {
|
||||
int local;
|
||||
intRefSource(local);
|
||||
sink(local); // tainted
|
||||
sink(local); // $ ast=416:7 ast=417:16 MISSING: ir
|
||||
}
|
||||
|
||||
void intPointerSourceCaller() {
|
||||
int local;
|
||||
intPointerSource(&local);
|
||||
sink(local); // tainted
|
||||
sink(local); // $ ast=422:7 ast=423:20 MISSING: ir
|
||||
}
|
||||
|
||||
void intPointerSourceCaller2() {
|
||||
int local[1];
|
||||
intPointerSource(local);
|
||||
sink(local); // tainted
|
||||
sink(*local); // tainted
|
||||
sink(local); // $ ast=428:7 ast=429:20 MISSING: ir
|
||||
sink(*local); // $ ast=428:7 ast=429:20 MISSING: ir
|
||||
}
|
||||
|
||||
void intArraySourceCaller() {
|
||||
int local;
|
||||
intArraySource(&local, 1);
|
||||
sink(local); // tainted
|
||||
sink(local); // $ ast=435:7 ast=436:18 MISSING: ir
|
||||
}
|
||||
|
||||
void intArraySourceCaller2() {
|
||||
int local[2];
|
||||
intArraySource(local, 2);
|
||||
sink(local); // tainted
|
||||
sink(*local); // tainted
|
||||
sink(local); // $ ast=441:7 ast=442:18 MISSING: ir
|
||||
sink(*local); // $ ast=441:7 ast=442:18 MISSING: ir
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void throughStmtExpr(int source1, int clean1) {
|
||||
sink( ({ source1; }) ); // tainted
|
||||
sink( ({ source1; }) ); // $ ast,ir
|
||||
sink( ({ clean1; }) ); // clean
|
||||
|
||||
int local = ({
|
||||
@@ -458,7 +458,7 @@ void throughStmtExpr(int source1, int clean1) {
|
||||
tmp = clean1;
|
||||
tmp;
|
||||
});
|
||||
sink(local); // tainted
|
||||
sink(local); // $ ast,ir
|
||||
}
|
||||
|
||||
void intOutparamSource(int *p) {
|
||||
@@ -468,5 +468,5 @@ void intOutparamSource(int *p) {
|
||||
void viaOutparam() {
|
||||
int x = 0;
|
||||
intOutparamSource(&x);
|
||||
sink(x); // tainted
|
||||
}
|
||||
sink(x); // $ ast,ir
|
||||
}
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
| BarrierGuard.cpp:9:10:9:15 | source | BarrierGuard.cpp:5:19:5:24 | source |
|
||||
| BarrierGuard.cpp:15:10:15:15 | source | BarrierGuard.cpp:13:17:13:22 | source |
|
||||
| BarrierGuard.cpp:25:10:25:15 | source | BarrierGuard.cpp:21:17:21:22 | source |
|
||||
| BarrierGuard.cpp:31:10:31:15 | source | BarrierGuard.cpp:29:16:29:21 | source |
|
||||
| BarrierGuard.cpp:33:10:33:15 | source | BarrierGuard.cpp:29:16:29:21 | source |
|
||||
| BarrierGuard.cpp:51:13:51:13 | x | BarrierGuard.cpp:49:10:49:15 | call to source |
|
||||
| BarrierGuard.cpp:53:13:53:13 | x | BarrierGuard.cpp:49:10:49:15 | call to source |
|
||||
| BarrierGuard.cpp:55:13:55:13 | x | BarrierGuard.cpp:49:10:49:15 | call to source |
|
||||
| BarrierGuard.cpp:62:14:62:14 | x | BarrierGuard.cpp:60:11:60:16 | call to source |
|
||||
| BarrierGuard.cpp:64:14:64:14 | x | BarrierGuard.cpp:60:11:60:16 | call to source |
|
||||
| BarrierGuard.cpp:66:14:66:14 | x | BarrierGuard.cpp:60:11:60:16 | call to source |
|
||||
| acrossLinkTargets.cpp:12:8:12:8 | x | acrossLinkTargets.cpp:19:27:19:32 | call to source |
|
||||
| clang.cpp:18:8:18:19 | sourceArray1 | clang.cpp:12:9:12:20 | sourceArray1 |
|
||||
| clang.cpp:22:8:22:20 | & ... | clang.cpp:12:9:12:20 | sourceArray1 |
|
||||
| clang.cpp:29:27:29:28 | m1 | clang.cpp:28:27:28:32 | call to source |
|
||||
| clang.cpp:30:27:30:34 | call to getFirst | clang.cpp:28:27:28:32 | call to source |
|
||||
| clang.cpp:37:10:37:11 | m2 | clang.cpp:34:32:34:37 | call to source |
|
||||
| clang.cpp:45:17:45:18 | m2 | clang.cpp:43:35:43:40 | call to source |
|
||||
| clang.cpp:51:8:51:17 | stackArray | clang.cpp:50:19:50:24 | call to source |
|
||||
| dispatch.cpp:11:38:11:38 | x | dispatch.cpp:37:19:37:24 | call to source |
|
||||
| dispatch.cpp:11:38:11:38 | x | dispatch.cpp:45:18:45:23 | call to source |
|
||||
| dispatch.cpp:35:16:35:25 | call to notSource1 | dispatch.cpp:9:37:9:42 | call to source |
|
||||
| dispatch.cpp:36:16:36:25 | call to notSource2 | dispatch.cpp:10:37:10:42 | call to source |
|
||||
| dispatch.cpp:43:15:43:24 | call to notSource1 | dispatch.cpp:9:37:9:42 | call to source |
|
||||
| dispatch.cpp:44:15:44:24 | call to notSource2 | dispatch.cpp:10:37:10:42 | call to source |
|
||||
| globals.cpp:6:10:6:14 | local | globals.cpp:5:17:5:22 | call to source |
|
||||
| lambdas.cpp:14:3:14:6 | t | lambdas.cpp:8:10:8:15 | call to source |
|
||||
| lambdas.cpp:18:8:18:8 | call to operator() | lambdas.cpp:8:10:8:15 | call to source |
|
||||
| lambdas.cpp:21:3:21:6 | t | lambdas.cpp:8:10:8:15 | call to source |
|
||||
| lambdas.cpp:29:3:29:6 | t | lambdas.cpp:8:10:8:15 | call to source |
|
||||
| lambdas.cpp:35:8:35:8 | a | lambdas.cpp:8:10:8:15 | call to source |
|
||||
| lambdas.cpp:41:8:41:8 | a | lambdas.cpp:8:10:8:15 | call to source |
|
||||
| lambdas.cpp:46:7:46:7 | w | lambdas.cpp:43:7:43:12 | call to source |
|
||||
| ref.cpp:56:10:56:11 | x1 | ref.cpp:53:9:53:10 | x1 |
|
||||
| ref.cpp:56:10:56:11 | x1 | ref.cpp:55:23:55:28 | call to source |
|
||||
| ref.cpp:59:10:59:11 | x2 | ref.cpp:53:13:53:14 | x2 |
|
||||
| ref.cpp:62:10:62:11 | x3 | ref.cpp:29:11:29:16 | call to source |
|
||||
| ref.cpp:62:10:62:11 | x3 | ref.cpp:53:17:53:18 | x3 |
|
||||
| ref.cpp:65:10:65:11 | x4 | ref.cpp:53:21:53:22 | x4 |
|
||||
| ref.cpp:123:13:123:15 | val | ref.cpp:122:23:122:28 | call to source |
|
||||
| ref.cpp:126:13:126:15 | val | ref.cpp:125:19:125:24 | call to source |
|
||||
| ref.cpp:129:13:129:15 | val | ref.cpp:94:15:94:20 | call to source |
|
||||
| ref.cpp:132:13:132:15 | val | ref.cpp:109:15:109:20 | call to source |
|
||||
| test.cpp:7:8:7:9 | t1 | test.cpp:6:12:6:17 | call to source |
|
||||
| test.cpp:9:8:9:9 | t1 | test.cpp:6:12:6:17 | call to source |
|
||||
| test.cpp:10:8:10:9 | t2 | test.cpp:6:12:6:17 | call to source |
|
||||
| test.cpp:15:8:15:9 | t2 | test.cpp:6:12:6:17 | call to source |
|
||||
| test.cpp:26:8:26:9 | t1 | test.cpp:6:12:6:17 | call to source |
|
||||
| test.cpp:30:8:30:8 | t | test.cpp:35:10:35:15 | call to source |
|
||||
| test.cpp:31:8:31:8 | c | test.cpp:36:13:36:18 | call to source |
|
||||
| test.cpp:58:10:58:10 | t | test.cpp:50:14:50:19 | call to source |
|
||||
| test.cpp:71:8:71:9 | x4 | test.cpp:66:30:66:36 | source1 |
|
||||
| test.cpp:76:8:76:9 | u1 | test.cpp:75:7:75:8 | u1 |
|
||||
| test.cpp:84:8:84:18 | ... ? ... : ... | test.cpp:83:7:83:8 | u2 |
|
||||
| test.cpp:86:8:86:9 | i1 | test.cpp:83:7:83:8 | u2 |
|
||||
| test.cpp:90:8:90:14 | source1 | test.cpp:89:28:89:34 | source1 |
|
||||
| test.cpp:103:10:103:12 | ref | test.cpp:100:13:100:18 | call to source |
|
||||
| test.cpp:140:8:140:8 | y | test.cpp:138:27:138:32 | call to source |
|
||||
| test.cpp:144:8:144:8 | s | test.cpp:151:33:151:38 | call to source |
|
||||
| test.cpp:152:8:152:8 | y | test.cpp:151:33:151:38 | call to source |
|
||||
| test.cpp:157:8:157:8 | x | test.cpp:164:34:164:39 | call to source |
|
||||
| test.cpp:165:8:165:8 | y | test.cpp:164:34:164:39 | call to source |
|
||||
| test.cpp:178:8:178:8 | y | test.cpp:171:11:171:16 | call to source |
|
||||
| test.cpp:260:12:260:12 | x | test.cpp:245:14:245:19 | call to source |
|
||||
| test.cpp:266:12:266:12 | x | test.cpp:265:22:265:27 | call to source |
|
||||
| test.cpp:289:14:289:14 | x | test.cpp:305:17:305:22 | call to source |
|
||||
| test.cpp:318:7:318:7 | x | test.cpp:314:4:314:9 | call to source |
|
||||
| test.cpp:349:10:349:18 | globalVar | test.cpp:347:17:347:22 | call to source |
|
||||
| test.cpp:365:10:365:14 | field | test.cpp:359:13:359:18 | call to source |
|
||||
| test.cpp:369:10:369:14 | field | test.cpp:373:13:373:18 | call to source |
|
||||
| test.cpp:375:10:375:14 | field | test.cpp:373:13:373:18 | call to source |
|
||||
| test.cpp:385:8:385:10 | tmp | test.cpp:382:48:382:54 | source1 |
|
||||
| test.cpp:392:8:392:10 | tmp | test.cpp:388:53:388:59 | source1 |
|
||||
| test.cpp:394:10:394:12 | tmp | test.cpp:388:53:388:59 | source1 |
|
||||
| test.cpp:401:8:401:10 | tmp | test.cpp:399:7:399:9 | tmp |
|
||||
| test.cpp:408:8:408:10 | tmp | test.cpp:405:7:405:9 | tmp |
|
||||
| test.cpp:418:8:418:12 | local | test.cpp:416:7:416:11 | local |
|
||||
| test.cpp:418:8:418:12 | local | test.cpp:417:16:417:20 | ref arg local |
|
||||
| test.cpp:424:8:424:12 | local | test.cpp:422:7:422:11 | local |
|
||||
| test.cpp:424:8:424:12 | local | test.cpp:423:20:423:25 | ref arg & ... |
|
||||
| test.cpp:430:8:430:12 | local | test.cpp:428:7:428:11 | local |
|
||||
| test.cpp:430:8:430:12 | local | test.cpp:429:20:429:24 | ref arg local |
|
||||
| test.cpp:431:8:431:13 | * ... | test.cpp:428:7:428:11 | local |
|
||||
| test.cpp:431:8:431:13 | * ... | test.cpp:429:20:429:24 | ref arg local |
|
||||
| test.cpp:437:8:437:12 | local | test.cpp:435:7:435:11 | local |
|
||||
| test.cpp:437:8:437:12 | local | test.cpp:436:18:436:23 | ref arg & ... |
|
||||
| test.cpp:443:8:443:12 | local | test.cpp:441:7:441:11 | local |
|
||||
| test.cpp:443:8:443:12 | local | test.cpp:442:18:442:22 | ref arg local |
|
||||
| test.cpp:444:8:444:13 | * ... | test.cpp:441:7:441:11 | local |
|
||||
| test.cpp:444:8:444:13 | * ... | test.cpp:442:18:442:22 | ref arg local |
|
||||
| test.cpp:450:9:450:22 | (statement expression) | test.cpp:449:26:449:32 | source1 |
|
||||
| test.cpp:461:8:461:12 | local | test.cpp:449:26:449:32 | source1 |
|
||||
| test.cpp:471:8:471:8 | x | test.cpp:465:8:465:13 | call to source |
|
||||
| true_upon_entry.cpp:21:8:21:8 | x | true_upon_entry.cpp:17:11:17:16 | call to source |
|
||||
| true_upon_entry.cpp:29:8:29:8 | x | true_upon_entry.cpp:27:9:27:14 | call to source |
|
||||
| true_upon_entry.cpp:39:8:39:8 | x | true_upon_entry.cpp:33:11:33:16 | call to source |
|
||||
| true_upon_entry.cpp:49:8:49:8 | x | true_upon_entry.cpp:43:11:43:16 | call to source |
|
||||
| true_upon_entry.cpp:57:8:57:8 | x | true_upon_entry.cpp:54:11:54:16 | call to source |
|
||||
| true_upon_entry.cpp:78:8:78:8 | x | true_upon_entry.cpp:70:11:70:16 | call to source |
|
||||
| true_upon_entry.cpp:86:8:86:8 | x | true_upon_entry.cpp:83:11:83:16 | call to source |
|
||||
|
||||
@@ -1,5 +1,27 @@
|
||||
import DataflowTestCommon
|
||||
|
||||
from DataFlow::Node sink, DataFlow::Node source, TestAllocationConfig cfg
|
||||
where cfg.hasFlow(source, sink)
|
||||
select sink, source
|
||||
class ASTDataFlowTest extends InlineExpectationsTest {
|
||||
ASTDataFlowTest() { this = "ASTDataFlowTest" }
|
||||
|
||||
override string getARelevantTag() { result = "ast" }
|
||||
|
||||
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(DataFlow::Node source, DataFlow::Node sink, TestAllocationConfig conf, int n |
|
||||
tag = "ast" and
|
||||
conf.hasFlow(source, sink) and
|
||||
n = strictcount(DataFlow::Node otherSource | conf.hasFlow(otherSource, sink)) and
|
||||
(
|
||||
n = 1 and value = ""
|
||||
or
|
||||
// If there is more than one source for this sink
|
||||
// we specify the source location explicitly.
|
||||
n > 1 and
|
||||
value =
|
||||
source.getLocation().getStartLine().toString() + ":" +
|
||||
source.getLocation().getStartColumn()
|
||||
) and
|
||||
location = sink.getLocation() and
|
||||
element = sink.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
| BarrierGuard.cpp:9:10:9:15 | source | BarrierGuard.cpp:5:19:5:24 | source |
|
||||
| BarrierGuard.cpp:15:10:15:15 | source | BarrierGuard.cpp:13:17:13:22 | source |
|
||||
| BarrierGuard.cpp:25:10:25:15 | source | BarrierGuard.cpp:21:17:21:22 | source |
|
||||
| BarrierGuard.cpp:31:10:31:15 | source | BarrierGuard.cpp:29:16:29:21 | source |
|
||||
| BarrierGuard.cpp:33:10:33:15 | source | BarrierGuard.cpp:29:16:29:21 | source |
|
||||
| BarrierGuard.cpp:53:13:53:13 | x | BarrierGuard.cpp:49:10:49:15 | call to source |
|
||||
| BarrierGuard.cpp:55:13:55:13 | x | BarrierGuard.cpp:49:10:49:15 | call to source |
|
||||
| BarrierGuard.cpp:64:14:64:14 | x | BarrierGuard.cpp:60:11:60:16 | call to source |
|
||||
| BarrierGuard.cpp:66:14:66:14 | x | BarrierGuard.cpp:60:11:60:16 | call to source |
|
||||
| acrossLinkTargets.cpp:12:8:12:8 | (int)... | acrossLinkTargets.cpp:19:27:19:32 | call to source |
|
||||
| acrossLinkTargets.cpp:12:8:12:8 | x | acrossLinkTargets.cpp:19:27:19:32 | call to source |
|
||||
| clang.cpp:18:8:18:19 | (const int *)... | clang.cpp:12:9:12:20 | sourceArray1 |
|
||||
| clang.cpp:18:8:18:19 | sourceArray1 | clang.cpp:12:9:12:20 | sourceArray1 |
|
||||
| clang.cpp:29:27:29:28 | m1 | clang.cpp:28:27:28:32 | call to source |
|
||||
| clang.cpp:30:27:30:34 | call to getFirst | clang.cpp:28:27:28:32 | call to source |
|
||||
| clang.cpp:37:10:37:11 | m2 | clang.cpp:34:32:34:37 | call to source |
|
||||
| clang.cpp:41:18:41:19 | m2 | clang.cpp:39:42:39:47 | call to source |
|
||||
| clang.cpp:45:17:45:18 | m2 | clang.cpp:43:35:43:40 | call to source |
|
||||
| dispatch.cpp:11:38:11:38 | x | dispatch.cpp:37:19:37:24 | call to source |
|
||||
| dispatch.cpp:11:38:11:38 | x | dispatch.cpp:45:18:45:23 | call to source |
|
||||
| dispatch.cpp:23:38:23:38 | x | dispatch.cpp:33:18:33:23 | call to source |
|
||||
| dispatch.cpp:23:38:23:38 | x | dispatch.cpp:41:17:41:22 | call to source |
|
||||
| dispatch.cpp:23:38:23:38 | x | dispatch.cpp:69:15:69:20 | call to source |
|
||||
| dispatch.cpp:23:38:23:38 | x | dispatch.cpp:73:14:73:19 | call to source |
|
||||
| dispatch.cpp:23:38:23:38 | x | dispatch.cpp:81:13:81:18 | call to source |
|
||||
| dispatch.cpp:31:16:31:24 | call to isSource1 | dispatch.cpp:22:37:22:42 | call to source |
|
||||
| dispatch.cpp:32:16:32:24 | call to isSource2 | dispatch.cpp:16:37:16:42 | call to source |
|
||||
| dispatch.cpp:35:16:35:25 | call to notSource1 | dispatch.cpp:9:37:9:42 | call to source |
|
||||
| dispatch.cpp:36:16:36:25 | call to notSource2 | dispatch.cpp:10:37:10:42 | call to source |
|
||||
| dispatch.cpp:39:15:39:23 | call to isSource1 | dispatch.cpp:22:37:22:42 | call to source |
|
||||
| dispatch.cpp:40:15:40:23 | call to isSource2 | dispatch.cpp:16:37:16:42 | call to source |
|
||||
| dispatch.cpp:43:15:43:24 | call to notSource1 | dispatch.cpp:9:37:9:42 | call to source |
|
||||
| dispatch.cpp:44:15:44:24 | call to notSource2 | dispatch.cpp:10:37:10:42 | call to source |
|
||||
| dispatch.cpp:55:22:55:30 | call to isSource1 | dispatch.cpp:22:37:22:42 | call to source |
|
||||
| dispatch.cpp:58:28:58:36 | call to isSource1 | dispatch.cpp:22:37:22:42 | call to source |
|
||||
| dispatch.cpp:96:8:96:8 | x | dispatch.cpp:107:17:107:22 | call to source |
|
||||
| dispatch.cpp:96:8:96:8 | x | dispatch.cpp:140:8:140:13 | call to source |
|
||||
| dispatch.cpp:96:8:96:8 | x | dispatch.cpp:144:8:144:13 | call to source |
|
||||
| globals.cpp:6:10:6:14 | local | globals.cpp:5:17:5:22 | call to source |
|
||||
| globals.cpp:12:10:12:24 | flowTestGlobal1 | globals.cpp:13:23:13:28 | call to source |
|
||||
| globals.cpp:19:10:19:24 | flowTestGlobal2 | globals.cpp:23:23:23:28 | call to source |
|
||||
| lambdas.cpp:14:3:14:6 | t | lambdas.cpp:8:10:8:15 | call to source |
|
||||
| lambdas.cpp:18:8:18:8 | call to operator() | lambdas.cpp:8:10:8:15 | call to source |
|
||||
| lambdas.cpp:29:3:29:6 | t | lambdas.cpp:8:10:8:15 | call to source |
|
||||
| lambdas.cpp:35:8:35:8 | a | lambdas.cpp:8:10:8:15 | call to source |
|
||||
| lambdas.cpp:41:8:41:8 | (reference dereference) | lambdas.cpp:8:10:8:15 | call to source |
|
||||
| lambdas.cpp:46:7:46:7 | w | lambdas.cpp:43:7:43:12 | call to source |
|
||||
| ref.cpp:56:10:56:11 | x1 | ref.cpp:55:23:55:28 | call to source |
|
||||
| ref.cpp:59:10:59:11 | x2 | ref.cpp:58:19:58:24 | call to source |
|
||||
| ref.cpp:62:10:62:11 | x3 | ref.cpp:29:11:29:16 | call to source |
|
||||
| ref.cpp:65:10:65:11 | x4 | ref.cpp:44:11:44:16 | call to source |
|
||||
| ref.cpp:123:13:123:15 | val | ref.cpp:122:23:122:28 | call to source |
|
||||
| ref.cpp:126:13:126:15 | val | ref.cpp:125:19:125:24 | call to source |
|
||||
| ref.cpp:129:13:129:15 | val | ref.cpp:94:15:94:20 | call to source |
|
||||
| ref.cpp:132:13:132:15 | val | ref.cpp:109:15:109:20 | call to source |
|
||||
| test.cpp:7:8:7:9 | t1 | test.cpp:6:12:6:17 | call to source |
|
||||
| test.cpp:9:8:9:9 | t1 | test.cpp:6:12:6:17 | call to source |
|
||||
| test.cpp:10:8:10:9 | t2 | test.cpp:6:12:6:17 | call to source |
|
||||
| test.cpp:15:8:15:9 | t2 | test.cpp:6:12:6:17 | call to source |
|
||||
| test.cpp:26:8:26:9 | t1 | test.cpp:6:12:6:17 | call to source |
|
||||
| test.cpp:30:8:30:8 | t | test.cpp:35:10:35:15 | call to source |
|
||||
| test.cpp:31:8:31:8 | c | test.cpp:36:13:36:18 | call to source |
|
||||
| test.cpp:58:10:58:10 | t | test.cpp:50:14:50:19 | call to source |
|
||||
| test.cpp:71:8:71:9 | x4 | test.cpp:66:30:66:36 | source1 |
|
||||
| test.cpp:90:8:90:14 | source1 | test.cpp:89:28:89:34 | source1 |
|
||||
| test.cpp:92:8:92:14 | source1 | test.cpp:89:28:89:34 | source1 |
|
||||
| test.cpp:110:10:110:12 | (reference dereference) | test.cpp:109:9:109:14 | call to source |
|
||||
| test.cpp:140:8:140:8 | y | test.cpp:138:27:138:32 | call to source |
|
||||
| test.cpp:144:8:144:8 | s | test.cpp:151:33:151:38 | call to source |
|
||||
| test.cpp:152:8:152:8 | y | test.cpp:151:33:151:38 | call to source |
|
||||
| test.cpp:157:8:157:8 | x | test.cpp:164:34:164:39 | call to source |
|
||||
| test.cpp:165:8:165:8 | y | test.cpp:164:34:164:39 | call to source |
|
||||
| test.cpp:178:8:178:8 | y | test.cpp:171:11:171:16 | call to source |
|
||||
| test.cpp:260:12:260:12 | x | test.cpp:245:14:245:19 | call to source |
|
||||
| test.cpp:266:12:266:12 | x | test.cpp:265:22:265:27 | call to source |
|
||||
| test.cpp:289:14:289:14 | x | test.cpp:305:17:305:22 | call to source |
|
||||
| test.cpp:318:7:318:7 | x | test.cpp:314:4:314:9 | call to source |
|
||||
| test.cpp:369:10:369:14 | field | test.cpp:373:13:373:18 | call to source |
|
||||
| test.cpp:375:10:375:14 | field | test.cpp:373:13:373:18 | call to source |
|
||||
| test.cpp:385:8:385:10 | tmp | test.cpp:382:48:382:54 | source1 |
|
||||
| test.cpp:392:8:392:10 | tmp | test.cpp:388:53:388:59 | source1 |
|
||||
| test.cpp:394:10:394:12 | tmp | test.cpp:388:53:388:59 | source1 |
|
||||
| test.cpp:450:9:450:22 | (statement expression) | test.cpp:449:26:449:32 | source1 |
|
||||
| test.cpp:461:8:461:12 | local | test.cpp:449:26:449:32 | source1 |
|
||||
| test.cpp:471:8:471:8 | x | test.cpp:465:8:465:13 | call to source |
|
||||
| true_upon_entry.cpp:13:8:13:8 | x | true_upon_entry.cpp:9:11:9:16 | call to source |
|
||||
| true_upon_entry.cpp:21:8:21:8 | x | true_upon_entry.cpp:17:11:17:16 | call to source |
|
||||
| true_upon_entry.cpp:29:8:29:8 | x | true_upon_entry.cpp:27:9:27:14 | call to source |
|
||||
| true_upon_entry.cpp:39:8:39:8 | x | true_upon_entry.cpp:33:11:33:16 | call to source |
|
||||
| true_upon_entry.cpp:49:8:49:8 | x | true_upon_entry.cpp:43:11:43:16 | call to source |
|
||||
| true_upon_entry.cpp:57:8:57:8 | x | true_upon_entry.cpp:54:11:54:16 | call to source |
|
||||
| true_upon_entry.cpp:66:8:66:8 | x | true_upon_entry.cpp:62:11:62:16 | call to source |
|
||||
| true_upon_entry.cpp:78:8:78:8 | x | true_upon_entry.cpp:70:11:70:16 | call to source |
|
||||
| true_upon_entry.cpp:86:8:86:8 | x | true_upon_entry.cpp:83:11:83:16 | call to source |
|
||||
| true_upon_entry.cpp:105:8:105:8 | x | true_upon_entry.cpp:98:11:98:16 | call to source |
|
||||
|
||||
@@ -1,5 +1,27 @@
|
||||
import IRDataflowTestCommon
|
||||
|
||||
from DataFlow::Node sink, DataFlow::Node source, TestAllocationConfig cfg
|
||||
where cfg.hasFlow(source, sink)
|
||||
select sink, source
|
||||
class IRDataFlowTest extends InlineExpectationsTest {
|
||||
IRDataFlowTest() { this = "IRDataFlowTest" }
|
||||
|
||||
override string getARelevantTag() { result = "ir" }
|
||||
|
||||
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(DataFlow::Node source, DataFlow::Node sink, TestAllocationConfig conf, int n |
|
||||
tag = "ir" and
|
||||
conf.hasFlow(source, sink) and
|
||||
n = strictcount(DataFlow::Node otherSource | conf.hasFlow(otherSource, sink)) and
|
||||
(
|
||||
n = 1 and value = ""
|
||||
or
|
||||
// If there is more than one source for this sink
|
||||
// we specify the source location explicitly.
|
||||
n > 1 and
|
||||
value =
|
||||
source.getLocation().getStartLine().toString() + ":" +
|
||||
source.getLocation().getStartColumn()
|
||||
) and
|
||||
location = sink.getLocation() and
|
||||
element = sink.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ int test1() {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
x = 0;
|
||||
}
|
||||
sink(x); // GOOD (x always overwritten)
|
||||
sink(x); // $ SPURIOUS: ir
|
||||
}
|
||||
|
||||
int test2(int iterations) {
|
||||
@@ -18,7 +18,7 @@ int test2(int iterations) {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
x = 0;
|
||||
}
|
||||
sink(x); // BAD
|
||||
sink(x); // $ ast,ir
|
||||
}
|
||||
|
||||
int test3() {
|
||||
@@ -26,7 +26,7 @@ int test3() {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
x = source();
|
||||
}
|
||||
sink(x); // BAD
|
||||
sink(x); // $ ast,ir
|
||||
}
|
||||
|
||||
int test4() {
|
||||
@@ -36,7 +36,7 @@ int test4() {
|
||||
break;
|
||||
x = 0;
|
||||
}
|
||||
sink(x); // BAD
|
||||
sink(x); // $ ast,ir
|
||||
}
|
||||
|
||||
int test5() {
|
||||
@@ -46,7 +46,7 @@ int test5() {
|
||||
continue;
|
||||
x = 0;
|
||||
}
|
||||
sink(x); // BAD
|
||||
sink(x); // $ ast,ir
|
||||
}
|
||||
|
||||
int test6() {
|
||||
@@ -54,7 +54,7 @@ int test6() {
|
||||
int x = source();
|
||||
for (int i = 0; i < 10 && (y = 1); i++) {
|
||||
}
|
||||
sink(x); // BAD
|
||||
sink(x); // $ ast,ir
|
||||
}
|
||||
|
||||
int test7() {
|
||||
@@ -63,7 +63,7 @@ int test7() {
|
||||
for (int i = 0; i < 10 && (y = 1); i++) {
|
||||
x = 0;
|
||||
}
|
||||
sink(x); // GOOD
|
||||
sink(x); // $ SPURIOUS: ir
|
||||
}
|
||||
|
||||
int test8() {
|
||||
@@ -75,7 +75,7 @@ int test8() {
|
||||
// jump out of the condition, not just the last one.
|
||||
for (int i = 0; i < 10 && (x = 1); i++) {
|
||||
}
|
||||
sink(x); // GOOD [false positive]
|
||||
sink(x); // $ SPURIOUS: ast,ir
|
||||
}
|
||||
|
||||
int test9() {
|
||||
@@ -83,14 +83,14 @@ int test9() {
|
||||
int x = source();
|
||||
for (int i = 0; (y = 1) && i < 10; i++) {
|
||||
}
|
||||
sink(x); // BAD
|
||||
sink(x); // $ ast,ir
|
||||
}
|
||||
|
||||
int test10() {
|
||||
int x = source();
|
||||
for (int i = 0; (x = 1) && i < 10; i++) {
|
||||
}
|
||||
sink(x); // GOOD
|
||||
sink(x); // no flow
|
||||
}
|
||||
|
||||
int test10(int b, int d) {
|
||||
@@ -102,5 +102,5 @@ int test10(int b, int d) {
|
||||
x = 0;
|
||||
L:
|
||||
}
|
||||
sink(x); // BAD
|
||||
sink(x); // $ ir MISSING: ast
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user