Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions cpp/ql/test/library-tests/dataflow/fields/A.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,21 @@ class A
cc.insert(nullptr);
ct.insert(new C());
sink(&cc); // no flow
sink(&ct); // flow
sink(&ct); // $ast $f-:ir
}
void f1()
{
C *c = new C();
B *b = B::make(c);
sink(b->c); // flow
sink(b->c); // $ast $f-:ir
}

void f2()
{
B *b = new B();
b->set(new C1());
sink(b->get()); // flow
sink((new B(new C()))->get()); // flow
sink(b->get()); // $ast $f-:ir
sink((new B(new C()))->get()); // $ast $f-:ir
}

void f3()
Expand All @@ -63,7 +63,7 @@ class A
B *b2;
b2 = setOnB(b1, new C2());
sink(b1->c); // no flow
sink(b2->c); // flow
sink(b2->c); // $ast $f-:ir
}

void f4()
Expand All @@ -72,7 +72,7 @@ class A
B *b2;
b2 = setOnBWrap(b1, new C2());
sink(b1->c); // no flow
sink(b2->c); // flow
sink(b2->c); // $ast $f-:ir
}

B *setOnBWrap(B *b1, C *c)
Expand Down Expand Up @@ -104,7 +104,7 @@ class A
{
if (C1 *c1 = dynamic_cast<C1 *>(c))
{
sink(c1->a); // flow
sink(c1->a); // $ast $f-:ir
}
C *cc;
if (C2 *c2 = dynamic_cast<C2 *>(c))
Expand All @@ -117,7 +117,7 @@ class A
}
if (C1 *c1 = dynamic_cast<C1 *>(cc))
{
sink(c1->a); // no flow, stopped by cast to C2 [FALSE POSITIVE]
sink(c1->a); //$f+:ast
}
}

Expand All @@ -129,7 +129,7 @@ class A
{
B *b = new B();
f7(b);
sink(b->c); // flow
sink(b->c); // $ast $f-:ir
}

class D
Expand All @@ -149,9 +149,9 @@ class A
{
B *b = new B();
D *d = new D(b, r());
sink(d->b); // flow x2
sink(d->b->c); // flow
sink(b->c); // flow
sink(d->b); // $ast=143:25 $ast=150:12 $f-:ir
sink(d->b->c); // $ast $f-:ir
sink(b->c); // $ast,ir
}

void f10()
Expand All @@ -162,11 +162,11 @@ class A
MyList *l3 = new MyList(nullptr, l2);
sink(l3->head); // no flow, b is nested beneath at least one ->next
sink(l3->next->head); // no flow
sink(l3->next->next->head); // flow
sink(l3->next->next->head); // $ast $f-:ir
sink(l3->next->next->next->head); // no flow
for (MyList *l = l3; l != nullptr; l = l->next)
{
sink(l->head); // flow
sink(l->head); // $ast $f-:ir
}
}

Expand Down
4 changes: 2 additions & 2 deletions cpp/ql/test/library-tests/dataflow/fields/B.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class B
Elem *e = new Elem();
Box1 *b1 = new Box1(e, nullptr);
Box2 *b2 = new Box2(b1);
sink(b2->box1->elem1); // flow
sink(b2->box1->elem1); // $ast $f-:ir
sink(b2->box1->elem2); // no flow
}

Expand All @@ -16,7 +16,7 @@ class B
Box1 *b1 = new B::Box1(nullptr, e);
Box2 *b2 = new Box2(b1);
sink(b2->box1->elem1); // no flow
sink(b2->box1->elem2); // flow
sink(b2->box1->elem2); // $ast $f-:ir
}

static void sink(void *o) {}
Expand Down
8 changes: 4 additions & 4 deletions cpp/ql/test/library-tests/dataflow/fields/C.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ class C

void func()
{
sink(s1); // flow
sink(s2); // flow [NOT DETECTED]
sink(s3); // flow
sink(s4); // flow [NOT DETECTED]
sink(s1); // $ast $f-:ir
sink(s2); // $f-:ast $f-:ir
sink(s3); // $ast $f-:ir
sink(s4); // $f-:ast $f-:ir
}

static void sink(const void *o) {}
Expand Down
4 changes: 2 additions & 2 deletions cpp/ql/test/library-tests/dataflow/fields/D.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class D {
};

static void sinkWrap(Box2* b2) {
sink(b2->getBox1()->getElem());
sink(b2->getBox1()->getElem()); // $ast=28:15 $ast=35:15 $ast=42:15 $ast=49:15 $f-:ir
}

Box2* boxfield;
Expand Down Expand Up @@ -61,6 +61,6 @@ class D {

private:
void f5b() {
sink(boxfield->box->elem);
sink(boxfield->box->elem); // $ast $f-:ir
}
};
6 changes: 3 additions & 3 deletions cpp/ql/test/library-tests/dataflow/fields/E.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ void sink(char *b);

void handlePacket(packet *p)
{
sink(p->data.buffer);
sink(p->data.buffer); // $ast $f-:ir
}

void f(buf* b)
Expand All @@ -28,7 +28,7 @@ void f(buf* b)
argument_source(raw);
argument_source(b->buffer);
argument_source(p.data.buffer);
sink(raw);
sink(b->buffer);
sink(raw); // $ast $f-:ir
sink(b->buffer); // $ast $f-:ir
handlePacket(&p);
}
16 changes: 8 additions & 8 deletions cpp/ql/test/library-tests/dataflow/fields/aliasing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,21 @@ void callSetters() {
referenceSetter(s2);
copySetter(s3);

sink(s1.m1); // flow
sink(s2.m1); // flow
sink(s1.m1); // $ast,ir
sink(s2.m1); // $ast,ir
sink(s3.m1); // no flow
}

void assignAfterAlias() {
S s1 = { 0, 0 };
S &ref1 = s1;
ref1.m1 = user_input();
sink(s1.m1); // flow [FALSE NEGATIVE]
sink(s1.m1); // $f-:ast $ir

S s2 = { 0, 0 };
S &ref2 = s2;
s2.m1 = user_input();
sink(ref2.m1); // flow [FALSE NEGATIVE]
sink(ref2.m1); // $f-:ast $ir
}

void assignAfterCopy() {
Expand All @@ -59,7 +59,7 @@ void assignBeforeCopy() {
S s2 = { 0, 0 };
s2.m1 = user_input();
S copy2 = s2;
sink(copy2.m1); // flow
sink(copy2.m1); // $ast,ir
}

struct Wrapper {
Expand All @@ -77,18 +77,18 @@ void pointerIntermediate() {
Wrapper w = { { 0, 0 } };
S *s = &w.s;
s->m1 = user_input();
sink(w.s.m1); // flow [FALSE NEGATIVE]
sink(w.s.m1); // $f-:ast $ir
}

void referenceIntermediate() {
Wrapper w = { { 0, 0 } };
S &s = w.s;
s.m1 = user_input();
sink(w.s.m1); // flow [FALSE NEGATIVE]
sink(w.s.m1); // $f-:ast $ir
}

void nestedAssign() {
Wrapper w = { { 0, 0 } };
w.s.m1 = user_input();
sink(w.s.m1); // flow
sink(w.s.m1); // $ast,ir
}
32 changes: 16 additions & 16 deletions cpp/ql/test/library-tests/dataflow/fields/by_reference.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,25 +48,25 @@ struct S {
void test_setDirectly() {
S s;
s.setDirectly(user_input());
sink(s.getDirectly()); // flow
sink(s.getDirectly()); // $ast $f-:ir
}

void test_setIndirectly() {
S s;
s.setIndirectly(user_input());
sink(s.getIndirectly()); // flow
sink(s.getIndirectly()); // $ast $f-:ir
}

void test_setThroughNonMember() {
S s;
s.setThroughNonMember(user_input());
sink(s.getThroughNonMember()); // flow
sink(s.getThroughNonMember()); // $ast $f-:ir
}

void test_nonMemberSetA() {
S s;
nonMemberSetA(&s, user_input());
sink(nonMemberGetA(&s)); // flow
sink(nonMemberGetA(&s)); // $ast $f-:ir
}

////////////////////
Expand Down Expand Up @@ -107,13 +107,13 @@ void test_outer_with_ptr(Outer *pouter) {
taint_inner_a_ptr(pouter->inner_ptr);
taint_a_ptr(&pouter->a);

sink(outer.inner_nested.a); // flow
sink(outer.inner_ptr->a); // flow [NOT DETECTED by IR]
sink(outer.a); // flow [NOT DETECTED]
sink(outer.inner_nested.a); // $ast,ir
sink(outer.inner_ptr->a); // $ast $f-:ir
sink(outer.a); // $f-:ast $f-:ir

sink(pouter->inner_nested.a); // flow
sink(pouter->inner_ptr->a); // flow [NOT DETECTED by IR]
sink(pouter->a); // flow [NOT DETECTED]
sink(pouter->inner_nested.a); // $ast,ir
sink(pouter->inner_ptr->a); // $ast $f-:ir
sink(pouter->a); // $f-:ast $f-:ir
}

void test_outer_with_ref(Outer *pouter) {
Expand All @@ -127,11 +127,11 @@ void test_outer_with_ref(Outer *pouter) {
taint_inner_a_ref(*pouter->inner_ptr);
taint_a_ref(pouter->a);

sink(outer.inner_nested.a); // flow
sink(outer.inner_ptr->a); // flow [NOT DETECTED by IR]
sink(outer.a); // flow [NOT DETECTED by IR]
sink(outer.inner_nested.a); // $ast,ir
sink(outer.inner_ptr->a); // $ast $f-:ir
sink(outer.a); // $ast $f-:ir

sink(pouter->inner_nested.a); // flow
sink(pouter->inner_ptr->a); // flow [NOT DETECTED by IR]
sink(pouter->a); // flow [NOT DETECTED by IR]
sink(pouter->inner_nested.a); // $ast,ir
sink(pouter->inner_ptr->a); // $ast $f-:ir
sink(pouter->a); // $ast $f-:ir
}
37 changes: 22 additions & 15 deletions cpp/ql/test/library-tests/dataflow/fields/complex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ class Bar
Bar() : f(0, 0) {}
};

class Outer
{
public:
Bar inner;
};

int user_input()
{
return 42;
Expand All @@ -31,31 +37,32 @@ void sink(int x)
{
}

void bar(Bar &b)
void bar(Outer &b)
{
// The library correctly finds that the four `user_input` sources can make it
// to the `sink` calls, but it also finds some source/sink combinations that
// are impossible. Those false positives here are a consequence of how the
// shared data flow library overapproximates field flow. The library only
// tracks the head (`f`) and the length (2) of the field access path, and
// then it tracks that both `a_` and `b_` have followed `f` in _some_ access
// path somewhere in the search. That makes the library conclude that there
// could be flow to `b.f.a_` even when the flow was actually to `b.f.b_`.
sink(b.f.a()); // flow [FALSE POSITIVE through `b2.f.setB` and `b3.f.setB`]
sink(b.f.b()); // flow [FALSE POSITIVE through `b1.f.setA` and `b3.f.setA`]
// tracks the final two fields (`f` and `inner`) and the length (3) of the field
// access path, and then it tracks that both `a_` and `b_` have followed `f.inner`
// in _some_ access path somewhere in the search. That makes the library conclude
// that there could be flow to `b.inner.f.a_` even when the flow was actually to
// `b.inner.f.b_`.
sink(b.inner.f.a()); // $ast=62:19 $f+:ast=63:19 $ast=64:19 $f+:ast=65:19 $f-:ir
sink(b.inner.f.b()); // $f+:ast=62:19 $ast=63:19 $f+:ast=64:19 $ast=65:19 $f-:ir
}

void foo()
{
Bar b1;
Bar b2;
Bar b3;
Bar b4;
Outer b1;
Outer b2;
Outer b3;
Outer b4;

b1.f.setA(user_input());
b2.f.setB(user_input());
b3.f.setA(user_input());
b3.f.setB(user_input());
b1.inner.f.setA(user_input());
b2.inner.f.setB(user_input());
b3.inner.f.setA(user_input());
b3.inner.f.setB(user_input());

// Only a() should alert
bar(b1);
Expand Down
4 changes: 2 additions & 2 deletions cpp/ql/test/library-tests/dataflow/fields/constructors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ class Foo

void bar(Foo &f)
{
sink(f.a()); // flow (through `f` and `h`)
sink(f.b()); // flow (through `g` and `h`)
sink(f.a()); //$ast=34:11 $ast=36:11 $f-:ir
sink(f.b()); //$ast=35:14 $ast=36:25 $f-:ir
}

void foo()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ uniqueEnclosingCallable
uniqueTypeBound
| complex.cpp:22:11:22:17 | constructor init of field f [post-this] | Node should have one type bound but has 0. |
| complex.cpp:22:11:22:17 | constructor init of field f [pre-this] | Node should have one type bound but has 0. |
| complex.cpp:25:7:25:7 | constructor init of field inner [post-this] | Node should have one type bound but has 0. |
| complex.cpp:25:7:25:7 | constructor init of field inner [pre-this] | Node should have one type bound but has 0. |
uniqueTypeRepr
| complex.cpp:22:11:22:17 | constructor init of field f [post-this] | Node should have one type representation but has 0. |
| complex.cpp:22:11:22:17 | constructor init of field f [pre-this] | Node should have one type representation but has 0. |
| complex.cpp:25:7:25:7 | constructor init of field inner [post-this] | Node should have one type representation but has 0. |
| complex.cpp:25:7:25:7 | constructor init of field inner [pre-this] | Node should have one type representation but has 0. |
uniqueNodeLocation
| A.cpp:38:7:38:8 | call to C | Node should have one location but has 2. |
| A.cpp:39:7:39:8 | call to C | Node should have one location but has 2. |
Expand Down
Loading