mirror of
https://github.com/github/codeql.git
synced 2026-05-03 20:58:03 +02:00
C++ field flow: Add test.
This is a fairly direct translation of the Java field flow test to C++. Not all the `// flow` annotations are currently accurate.
This commit is contained in:
committed by
Jonas Jensen
parent
dccc0f4db1
commit
6d4d131ad4
187
cpp/ql/test/library-tests/dataflow/fields/A.cpp
Normal file
187
cpp/ql/test/library-tests/dataflow/fields/A.cpp
Normal file
@@ -0,0 +1,187 @@
|
||||
class A
|
||||
{
|
||||
|
||||
class C
|
||||
{
|
||||
public:
|
||||
virtual void f(void *) {}
|
||||
};
|
||||
class C1 : public C
|
||||
{
|
||||
public:
|
||||
A *a;
|
||||
};
|
||||
class C2 : public C
|
||||
{
|
||||
};
|
||||
|
||||
class B
|
||||
{
|
||||
public:
|
||||
C *c;
|
||||
B() {}
|
||||
B(C *c)
|
||||
{
|
||||
this->c = c;
|
||||
}
|
||||
void set(C *c) { this->c = c; }
|
||||
C *get() { return this->c; }
|
||||
static B *make(C *c)
|
||||
{
|
||||
return new B(c);
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
void f0()
|
||||
{
|
||||
C cc;
|
||||
C ct;
|
||||
cc.f(nullptr);
|
||||
ct.f(new C());
|
||||
sink(&cc); // no flow
|
||||
sink(&ct); // flow
|
||||
}
|
||||
void f1()
|
||||
{
|
||||
C *c = new C();
|
||||
B *b = B::make(c);
|
||||
sink(b->c); // flow
|
||||
}
|
||||
|
||||
void f2()
|
||||
{
|
||||
B *b = new B();
|
||||
b->set(new C1());
|
||||
sink(b->get()); // flow
|
||||
sink((new B(new C()))->get()); // flow
|
||||
}
|
||||
|
||||
void f3()
|
||||
{
|
||||
B *b1 = new B();
|
||||
B *b2;
|
||||
b2 = setOnB(b1, new C2());
|
||||
sink(b1->c); // no flow
|
||||
sink(b2->c); // flow
|
||||
}
|
||||
|
||||
void f4()
|
||||
{
|
||||
B *b1 = new B();
|
||||
B *b2;
|
||||
b2 = setOnBWrap(b1, new C2());
|
||||
sink(b1->c); // no flow
|
||||
sink(b2->c); // flow
|
||||
}
|
||||
|
||||
B *setOnBWrap(B *b1, C *c)
|
||||
{
|
||||
B *b2;
|
||||
b2 = setOnB(b1, c);
|
||||
return r() ? b1 : b2;
|
||||
}
|
||||
|
||||
A::B *setOnB(B *b1, C *c)
|
||||
{
|
||||
if (r())
|
||||
{
|
||||
B *b2 = new B();
|
||||
b2->set(c);
|
||||
return b2;
|
||||
}
|
||||
return b1;
|
||||
}
|
||||
|
||||
void f5()
|
||||
{
|
||||
A *a = new A();
|
||||
C1 *c1 = new C1();
|
||||
c1->a = a;
|
||||
f6(c1);
|
||||
}
|
||||
void f6(C *c)
|
||||
{
|
||||
if (C1 *c1 = dynamic_cast<C1 *>(c))
|
||||
{
|
||||
sink(c1->a); // flow
|
||||
}
|
||||
C *cc;
|
||||
if (C2 *c2 = dynamic_cast<C2 *>(c))
|
||||
{
|
||||
cc = c2;
|
||||
}
|
||||
else
|
||||
{
|
||||
cc = new C1();
|
||||
}
|
||||
if (C1 *c1 = dynamic_cast<C1 *>(cc))
|
||||
{
|
||||
sink(c1->a); // no flow, stopped by cast to C2
|
||||
}
|
||||
}
|
||||
|
||||
void f7(B *b)
|
||||
{
|
||||
b->set(new C());
|
||||
}
|
||||
void f8()
|
||||
{
|
||||
B *b = new B();
|
||||
f7(b);
|
||||
sink(b->c); // flow
|
||||
}
|
||||
|
||||
class D
|
||||
{
|
||||
public:
|
||||
A::B *b;
|
||||
|
||||
D(A::B *b, bool x)
|
||||
{
|
||||
b->c = new C();
|
||||
this->b = x ? b : new B();
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
f9()
|
||||
{
|
||||
B *b = new B();
|
||||
D *d = new D(b, r());
|
||||
sink(d->b); // flow x2
|
||||
sink(d->b->c); // flow
|
||||
sink(b->c); // flow
|
||||
}
|
||||
|
||||
void f10()
|
||||
{
|
||||
B *b = new B();
|
||||
MyList *l1 = new MyList(b, new MyList(nullptr, nullptr));
|
||||
MyList *l2 = new MyList(nullptr, l1);
|
||||
MyList *l3 = new MyList(nullptr, l2);
|
||||
sink(l3->head); // no flow, b is nested beneath at least one ->next
|
||||
sink(l3->next->head); // flow, the precise nesting depth isn't tracked
|
||||
sink(l3->next->next->head); // flow
|
||||
sink(l3->next->next->next->head); // flow
|
||||
for (MyList *l = l3; l != nullptr; l = l->next)
|
||||
{
|
||||
sink(l->head); // flow
|
||||
}
|
||||
}
|
||||
|
||||
static void sink(void *o) {}
|
||||
bool r() { return reinterpret_cast<long long>(this) % 10 > 5; }
|
||||
|
||||
class MyList
|
||||
{
|
||||
public:
|
||||
B *head;
|
||||
MyList *next;
|
||||
MyList(B *newHead, MyList *next)
|
||||
{
|
||||
head = newHead;
|
||||
this->next = next;
|
||||
}
|
||||
};
|
||||
};
|
||||
49
cpp/ql/test/library-tests/dataflow/fields/B.cpp
Normal file
49
cpp/ql/test/library-tests/dataflow/fields/B.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
class B
|
||||
{
|
||||
|
||||
void f1()
|
||||
{
|
||||
Elem *e = new Elem();
|
||||
Box1 *b1 = new Box1(e, nullptr);
|
||||
Box2 *b2 = new Box2(b1);
|
||||
sink(b2->box1->elem1); // flow
|
||||
sink(b2->box1->elem2); // FP due to flow in f2 below
|
||||
}
|
||||
|
||||
void f2()
|
||||
{
|
||||
Elem *e = new B::Elem();
|
||||
Box1 *b1 = new B::Box1(nullptr, e);
|
||||
Box2 *b2 = new Box2(b1);
|
||||
sink(b2->box1->elem1); // FP due to flow in f1 above
|
||||
sink(b2->box1->elem2); // flow
|
||||
}
|
||||
|
||||
static void sink(void *o) {}
|
||||
|
||||
class Elem
|
||||
{
|
||||
};
|
||||
|
||||
class Box1
|
||||
{
|
||||
public:
|
||||
Elem *elem1;
|
||||
Elem *elem2;
|
||||
Box1(Elem *e1, Elem *e2)
|
||||
{
|
||||
this->elem1 = e1;
|
||||
this->elem2 = e2;
|
||||
}
|
||||
};
|
||||
|
||||
class Box2
|
||||
{
|
||||
public:
|
||||
Box1 *box1;
|
||||
Box2(Box1 *b1)
|
||||
{
|
||||
this->box1 = b1;
|
||||
}
|
||||
};
|
||||
};
|
||||
37
cpp/ql/test/library-tests/dataflow/fields/C.cpp
Normal file
37
cpp/ql/test/library-tests/dataflow/fields/C.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
class C
|
||||
{
|
||||
class Elem
|
||||
{
|
||||
};
|
||||
|
||||
private:
|
||||
Elem *s1 = new Elem();
|
||||
const Elem *s2 = new Elem();
|
||||
Elem *s3;
|
||||
|
||||
public:
|
||||
const static Elem *s4;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
C *c = new C();
|
||||
c->func();
|
||||
}
|
||||
|
||||
C() : s1(new Elem())
|
||||
{
|
||||
this->s3 = new Elem();
|
||||
}
|
||||
|
||||
void func()
|
||||
{
|
||||
sink(s1);
|
||||
sink(s2);
|
||||
sink(s3);
|
||||
sink(s4);
|
||||
}
|
||||
|
||||
static void sink(const void *o) {}
|
||||
};
|
||||
const C::Elem *C::s4 = new Elem();
|
||||
112
cpp/ql/test/library-tests/dataflow/fields/flow.expected
Normal file
112
cpp/ql/test/library-tests/dataflow/fields/flow.expected
Normal file
@@ -0,0 +1,112 @@
|
||||
edges
|
||||
| A.cpp:41:10:41:16 | new [void] | A.cpp:43:10:43:12 | & ... |
|
||||
| A.cpp:47:12:47:18 | new [void] | A.cpp:48:20:48:20 | c [void] |
|
||||
| A.cpp:48:12:48:18 | call to make [c, ... (1)] | A.cpp:49:10:49:10 | b [c, ... (1)] |
|
||||
| A.cpp:48:20:48:20 | c [void] | A.cpp:48:12:48:18 | call to make [c, ... (1)] |
|
||||
| A.cpp:49:10:49:10 | b [c, ... (1)] | A.cpp:49:13:49:13 | c |
|
||||
| A.cpp:55:5:55:5 | b [post update] [c, ... (1)] | A.cpp:56:10:56:10 | b [c, ... (1)] |
|
||||
| A.cpp:55:12:55:19 | new [void] | A.cpp:55:5:55:5 | b [post update] [c, ... (1)] |
|
||||
| A.cpp:56:10:56:10 | b [c, ... (1)] | A.cpp:56:13:56:15 | call to get |
|
||||
| A.cpp:57:11:57:24 | call to B [post update] [c, ... (1)] | A.cpp:57:11:57:24 | new [c, ... (1)] |
|
||||
| A.cpp:57:11:57:24 | new [c, ... (1)] | A.cpp:57:28:57:30 | call to get |
|
||||
| A.cpp:57:17:57:23 | new [void] | A.cpp:57:11:57:24 | call to B [post update] [c, ... (1)] |
|
||||
| A.cpp:64:10:64:15 | call to setOnB [c, ... (1)] | A.cpp:66:10:66:11 | b2 [c, ... (1)] |
|
||||
| A.cpp:64:21:64:28 | new [void] | A.cpp:64:10:64:15 | call to setOnB [c, ... (1)] |
|
||||
| A.cpp:66:10:66:11 | b2 [c, ... (1)] | A.cpp:66:14:66:14 | c |
|
||||
| A.cpp:73:10:73:19 | call to setOnBWrap [c, ... (1)] | A.cpp:75:10:75:11 | b2 [c, ... (1)] |
|
||||
| A.cpp:73:25:73:32 | new [void] | A.cpp:73:10:73:19 | call to setOnBWrap [c, ... (1)] |
|
||||
| A.cpp:75:10:75:11 | b2 [c, ... (1)] | A.cpp:75:14:75:14 | c |
|
||||
| A.cpp:98:12:98:18 | new [void] | A.cpp:100:5:100:13 | ... = ... [void] |
|
||||
| A.cpp:100:5:100:6 | c1 [post update] [a, ... (1)] | A.cpp:101:8:101:9 | c1 [a, ... (1)] |
|
||||
| A.cpp:100:5:100:13 | ... = ... [void] | A.cpp:100:5:100:6 | c1 [post update] [a, ... (1)] |
|
||||
| A.cpp:101:8:101:9 | c1 [a, ... (1)] | A.cpp:103:14:103:14 | c [a, ... (1)] |
|
||||
| A.cpp:103:14:103:14 | c [a, ... (1)] | A.cpp:107:12:107:13 | c1 [a, ... (1)] |
|
||||
| A.cpp:103:14:103:14 | c [a, ... (1)] | A.cpp:120:12:120:13 | c1 [a, ... (1)] |
|
||||
| A.cpp:107:12:107:13 | c1 [a, ... (1)] | A.cpp:107:16:107:16 | a |
|
||||
| A.cpp:120:12:120:13 | c1 [a, ... (1)] | A.cpp:120:16:120:16 | a |
|
||||
| A.cpp:126:5:126:5 | b [post update] [c, ... (1)] | A.cpp:131:8:131:8 | b [post update] [c, ... (1)] |
|
||||
| A.cpp:126:12:126:18 | new [void] | A.cpp:126:5:126:5 | b [post update] [c, ... (1)] |
|
||||
| A.cpp:131:8:131:8 | b [post update] [c, ... (1)] | A.cpp:132:10:132:10 | b [c, ... (1)] |
|
||||
| A.cpp:132:10:132:10 | b [c, ... (1)] | A.cpp:132:13:132:13 | c |
|
||||
| A.cpp:142:7:142:7 | b [post update] [c, ... (1)] | A.cpp:143:7:143:31 | ... = ... [c, ... (1)] |
|
||||
| A.cpp:142:7:142:7 | b [post update] [c, ... (1)] | A.cpp:151:18:151:18 | b [post update] [c, ... (1)] |
|
||||
| A.cpp:142:7:142:20 | ... = ... [void] | A.cpp:142:7:142:7 | b [post update] [c, ... (1)] |
|
||||
| A.cpp:142:14:142:20 | new [void] | A.cpp:142:7:142:20 | ... = ... [void] |
|
||||
| A.cpp:143:7:143:10 | this [post update] [b, ... (1)] | A.cpp:151:12:151:24 | call to D [post update] [b, ... (1)] |
|
||||
| A.cpp:143:7:143:10 | this [post update] [b, ... (2)] | A.cpp:151:12:151:24 | call to D [post update] [b, ... (2)] |
|
||||
| A.cpp:143:7:143:31 | ... = ... [c, ... (1)] | A.cpp:143:7:143:10 | this [post update] [b, ... (2)] |
|
||||
| A.cpp:143:7:143:31 | ... = ... [void] | A.cpp:143:7:143:10 | this [post update] [b, ... (1)] |
|
||||
| A.cpp:143:25:143:31 | new [void] | A.cpp:143:7:143:31 | ... = ... [void] |
|
||||
| A.cpp:150:12:150:18 | new [void] | A.cpp:151:18:151:18 | b [void] |
|
||||
| A.cpp:151:12:151:24 | call to D [post update] [b, ... (1)] | A.cpp:152:10:152:10 | d [b, ... (1)] |
|
||||
| A.cpp:151:12:151:24 | call to D [post update] [b, ... (2)] | A.cpp:153:10:153:10 | d [b, ... (2)] |
|
||||
| A.cpp:151:18:151:18 | b [post update] [c, ... (1)] | A.cpp:154:10:154:10 | b [c, ... (1)] |
|
||||
| A.cpp:151:18:151:18 | b [void] | A.cpp:151:12:151:24 | call to D [post update] [b, ... (1)] |
|
||||
| A.cpp:152:10:152:10 | d [b, ... (1)] | A.cpp:152:13:152:13 | b |
|
||||
| A.cpp:153:10:153:10 | d [b, ... (2)] | A.cpp:153:13:153:13 | b [c, ... (1)] |
|
||||
| A.cpp:153:13:153:13 | b [c, ... (1)] | A.cpp:153:16:153:16 | c |
|
||||
| A.cpp:154:10:154:10 | b [c, ... (1)] | A.cpp:154:13:154:13 | c |
|
||||
| A.cpp:159:12:159:18 | new [void] | A.cpp:160:29:160:29 | b [void] |
|
||||
| A.cpp:160:18:160:60 | call to MyList [post update] [head, ... (1)] | A.cpp:161:38:161:39 | l1 [head, ... (1)] |
|
||||
| A.cpp:160:29:160:29 | b [void] | A.cpp:160:18:160:60 | call to MyList [post update] [head, ... (1)] |
|
||||
| A.cpp:161:18:161:40 | call to MyList [post update] [next, ... (2)] | A.cpp:162:38:162:39 | l2 [next, ... (2)] |
|
||||
| A.cpp:161:38:161:39 | l1 [head, ... (1)] | A.cpp:161:18:161:40 | call to MyList [post update] [next, ... (2)] |
|
||||
| A.cpp:162:18:162:40 | call to MyList [post update] [next, ... (3)] | A.cpp:165:10:165:11 | l3 [next, ... (3)] |
|
||||
| A.cpp:162:18:162:40 | call to MyList [post update] [next, ... (3)] | A.cpp:167:44:167:44 | l [next, ... (3)] |
|
||||
| A.cpp:162:38:162:39 | l2 [next, ... (2)] | A.cpp:162:18:162:40 | call to MyList [post update] [next, ... (3)] |
|
||||
| A.cpp:165:10:165:11 | l3 [next, ... (3)] | A.cpp:165:14:165:17 | next [next, ... (2)] |
|
||||
| A.cpp:165:14:165:17 | next [next, ... (2)] | A.cpp:165:20:165:23 | next [head, ... (1)] |
|
||||
| A.cpp:165:20:165:23 | next [head, ... (1)] | A.cpp:165:26:165:29 | head |
|
||||
| A.cpp:167:44:167:44 | l [next, ... (2)] | A.cpp:167:47:167:50 | next [head, ... (1)] |
|
||||
| A.cpp:167:44:167:44 | l [next, ... (3)] | A.cpp:167:47:167:50 | next [next, ... (2)] |
|
||||
| A.cpp:167:47:167:50 | next [head, ... (1)] | A.cpp:169:12:169:12 | l [head, ... (1)] |
|
||||
| A.cpp:167:47:167:50 | next [next, ... (2)] | A.cpp:167:44:167:44 | l [next, ... (2)] |
|
||||
| A.cpp:169:12:169:12 | l [head, ... (1)] | A.cpp:169:15:169:18 | head |
|
||||
| B.cpp:6:15:6:24 | new [void] | B.cpp:7:25:7:25 | e [void] |
|
||||
| B.cpp:7:16:7:35 | call to Box1 [post update] [elem1, ... (1)] | B.cpp:8:25:8:26 | b1 [elem1, ... (1)] |
|
||||
| B.cpp:7:25:7:25 | e [void] | B.cpp:7:16:7:35 | call to Box1 [post update] [elem1, ... (1)] |
|
||||
| B.cpp:8:16:8:27 | call to Box2 [post update] [box1, ... (2)] | B.cpp:9:10:9:11 | b2 [box1, ... (2)] |
|
||||
| B.cpp:8:16:8:27 | call to Box2 [post update] [box1, ... (2)] | B.cpp:10:10:10:11 | b2 [box1, ... (2)] |
|
||||
| B.cpp:8:25:8:26 | b1 [elem1, ... (1)] | B.cpp:8:16:8:27 | call to Box2 [post update] [box1, ... (2)] |
|
||||
| B.cpp:9:10:9:11 | b2 [box1, ... (2)] | B.cpp:9:14:9:17 | box1 [elem1, ... (1)] |
|
||||
| B.cpp:9:14:9:17 | box1 [elem1, ... (1)] | B.cpp:9:20:9:24 | elem1 |
|
||||
| B.cpp:10:10:10:11 | b2 [box1, ... (2)] | B.cpp:10:14:10:17 | box1 [elem2, ... (1)] |
|
||||
| B.cpp:10:14:10:17 | box1 [elem2, ... (1)] | B.cpp:10:20:10:24 | elem2 |
|
||||
| B.cpp:15:15:15:27 | new [void] | B.cpp:16:37:16:37 | e [void] |
|
||||
| B.cpp:16:16:16:38 | call to Box1 [post update] [elem2, ... (1)] | B.cpp:17:25:17:26 | b1 [elem2, ... (1)] |
|
||||
| B.cpp:16:37:16:37 | e [void] | B.cpp:16:16:16:38 | call to Box1 [post update] [elem2, ... (1)] |
|
||||
| B.cpp:17:16:17:27 | call to Box2 [post update] [box1, ... (2)] | B.cpp:18:10:18:11 | b2 [box1, ... (2)] |
|
||||
| B.cpp:17:16:17:27 | call to Box2 [post update] [box1, ... (2)] | B.cpp:19:10:19:11 | b2 [box1, ... (2)] |
|
||||
| B.cpp:17:25:17:26 | b1 [elem2, ... (1)] | B.cpp:17:16:17:27 | call to Box2 [post update] [box1, ... (2)] |
|
||||
| B.cpp:18:10:18:11 | b2 [box1, ... (2)] | B.cpp:18:14:18:17 | box1 [elem1, ... (1)] |
|
||||
| B.cpp:18:14:18:17 | box1 [elem1, ... (1)] | B.cpp:18:20:18:24 | elem1 |
|
||||
| B.cpp:19:10:19:11 | b2 [box1, ... (2)] | B.cpp:19:14:19:17 | box1 [elem2, ... (1)] |
|
||||
| B.cpp:19:14:19:17 | box1 [elem2, ... (1)] | B.cpp:19:20:19:24 | elem2 |
|
||||
| C.cpp:18:12:18:18 | call to C [post update] [s3, ... (1)] | C.cpp:19:5:19:5 | c [s3, ... (1)] |
|
||||
| C.cpp:19:5:19:5 | c [s3, ... (1)] | C.cpp:27:8:27:11 | `this` parameter in func [s3, ... (1)] |
|
||||
| C.cpp:24:5:24:8 | this [post update] [s3, ... (1)] | C.cpp:18:12:18:18 | call to C [post update] [s3, ... (1)] |
|
||||
| C.cpp:24:5:24:25 | ... = ... [void] | C.cpp:24:5:24:8 | this [post update] [s3, ... (1)] |
|
||||
| C.cpp:24:16:24:25 | new [void] | C.cpp:24:5:24:25 | ... = ... [void] |
|
||||
| C.cpp:27:8:27:11 | `this` parameter in func [s3, ... (1)] | file://:0:0:0:0 | this [s3, ... (1)] |
|
||||
| file://:0:0:0:0 | this [s3, ... (1)] | C.cpp:31:10:31:11 | s3 |
|
||||
#select
|
||||
| A.cpp:43:10:43:12 | & ... | A.cpp:41:10:41:16 | new [void] | A.cpp:43:10:43:12 | & ... | & ... flows from $@ | A.cpp:41:10:41:16 | new [void] | new [void] |
|
||||
| A.cpp:49:13:49:13 | c | A.cpp:47:12:47:18 | new [void] | A.cpp:49:13:49:13 | c | c flows from $@ | A.cpp:47:12:47:18 | new [void] | new [void] |
|
||||
| A.cpp:56:13:56:15 | call to get | A.cpp:55:12:55:19 | new [void] | A.cpp:56:13:56:15 | call to get | call to get flows from $@ | A.cpp:55:12:55:19 | new [void] | new [void] |
|
||||
| A.cpp:57:28:57:30 | call to get | A.cpp:57:17:57:23 | new [void] | A.cpp:57:28:57:30 | call to get | call to get flows from $@ | A.cpp:57:17:57:23 | new [void] | new [void] |
|
||||
| A.cpp:66:14:66:14 | c | A.cpp:64:21:64:28 | new [void] | A.cpp:66:14:66:14 | c | c flows from $@ | A.cpp:64:21:64:28 | new [void] | new [void] |
|
||||
| A.cpp:75:14:75:14 | c | A.cpp:73:25:73:32 | new [void] | A.cpp:75:14:75:14 | c | c flows from $@ | A.cpp:73:25:73:32 | new [void] | new [void] |
|
||||
| A.cpp:107:16:107:16 | a | A.cpp:98:12:98:18 | new [void] | A.cpp:107:16:107:16 | a | a flows from $@ | A.cpp:98:12:98:18 | new [void] | new [void] |
|
||||
| A.cpp:120:16:120:16 | a | A.cpp:98:12:98:18 | new [void] | A.cpp:120:16:120:16 | a | a flows from $@ | A.cpp:98:12:98:18 | new [void] | new [void] |
|
||||
| A.cpp:132:13:132:13 | c | A.cpp:126:12:126:18 | new [void] | A.cpp:132:13:132:13 | c | c flows from $@ | A.cpp:126:12:126:18 | new [void] | new [void] |
|
||||
| A.cpp:152:13:152:13 | b | A.cpp:143:25:143:31 | new [void] | A.cpp:152:13:152:13 | b | b flows from $@ | A.cpp:143:25:143:31 | new [void] | new [void] |
|
||||
| A.cpp:152:13:152:13 | b | A.cpp:150:12:150:18 | new [void] | A.cpp:152:13:152:13 | b | b flows from $@ | A.cpp:150:12:150:18 | new [void] | new [void] |
|
||||
| A.cpp:153:16:153:16 | c | A.cpp:142:14:142:20 | new [void] | A.cpp:153:16:153:16 | c | c flows from $@ | A.cpp:142:14:142:20 | new [void] | new [void] |
|
||||
| A.cpp:154:13:154:13 | c | A.cpp:142:14:142:20 | new [void] | A.cpp:154:13:154:13 | c | c flows from $@ | A.cpp:142:14:142:20 | new [void] | new [void] |
|
||||
| A.cpp:165:26:165:29 | head | A.cpp:159:12:159:18 | new [void] | A.cpp:165:26:165:29 | head | head flows from $@ | A.cpp:159:12:159:18 | new [void] | new [void] |
|
||||
| A.cpp:169:15:169:18 | head | A.cpp:159:12:159:18 | new [void] | A.cpp:169:15:169:18 | head | head flows from $@ | A.cpp:159:12:159:18 | new [void] | new [void] |
|
||||
| B.cpp:9:20:9:24 | elem1 | B.cpp:6:15:6:24 | new [void] | B.cpp:9:20:9:24 | elem1 | elem1 flows from $@ | B.cpp:6:15:6:24 | new [void] | new [void] |
|
||||
| B.cpp:10:20:10:24 | elem2 | B.cpp:6:15:6:24 | new [void] | B.cpp:10:20:10:24 | elem2 | elem2 flows from $@ | B.cpp:6:15:6:24 | new [void] | new [void] |
|
||||
| B.cpp:18:20:18:24 | elem1 | B.cpp:15:15:15:27 | new [void] | B.cpp:18:20:18:24 | elem1 | elem1 flows from $@ | B.cpp:15:15:15:27 | new [void] | new [void] |
|
||||
| B.cpp:19:20:19:24 | elem2 | B.cpp:15:15:15:27 | new [void] | B.cpp:19:20:19:24 | elem2 | elem2 flows from $@ | B.cpp:15:15:15:27 | new [void] | new [void] |
|
||||
| C.cpp:31:10:31:11 | s3 | C.cpp:24:16:24:25 | new [void] | C.cpp:31:10:31:11 | s3 | s3 flows from $@ | C.cpp:24:16:24:25 | new [void] | new [void] |
|
||||
32
cpp/ql/test/library-tests/dataflow/fields/flow.ql
Normal file
32
cpp/ql/test/library-tests/dataflow/fields/flow.ql
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* @kind path-problem
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.dataflow.DataFlow
|
||||
import DataFlow::PathGraph
|
||||
import DataFlow
|
||||
import cpp
|
||||
class Conf extends Configuration {
|
||||
Conf() { this = "FieldFlowConf" }
|
||||
|
||||
override predicate isSource(Node src) { src.asExpr() instanceof NewExpr }
|
||||
|
||||
override predicate isSink(Node sink) {
|
||||
exists(Call c |
|
||||
c.getTarget().hasName("sink") and
|
||||
c.getAnArgument() = sink.asExpr()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isAdditionalFlowStep(Node a, Node b) {
|
||||
b.asPartialDefinition() = any(Call c |
|
||||
c.getTarget().hasName("f") and c.getAnArgument() = a.asExpr()
|
||||
).getQualifier()
|
||||
or
|
||||
b.asExpr().(AddressOfExpr).getOperand() = a.asExpr()
|
||||
}
|
||||
}
|
||||
|
||||
from DataFlow::PathNode src, DataFlow::PathNode sink, Conf conf
|
||||
where conf.hasFlowPath(src, sink)
|
||||
select sink, src, sink, sink + " flows from $@", src, src.toString()
|
||||
Reference in New Issue
Block a user