Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit faf9fd6

Browse files
committed
C++: Add a testcase (and a new test) to test flow through functions.
1 parent e1aef31 commit faf9fd6

10 files changed

Lines changed: 94 additions & 34 deletions

File tree

cpp/ql/test/library-tests/dataflow/dataflow-tests/BarrierGuard.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ void bg_stackstruct(XY s1, XY s2) {
5656
}
5757
}
5858

59-
void bg_structptr(XY *p1, XY *p2) {
59+
void bg_structptr(XY *p1, XY *p2) { // $ ast-def=p1 ast-def=p2
6060
p1->x = source();
6161
if (guarded(p1->x)) {
6262
sink(p1->x); // $ SPURIOUS: ast

cpp/ql/test/library-tests/dataflow/dataflow-tests/clang.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ struct twoIntFields {
88
int getFirst() { return m1; }
99
};
1010

11-
void following_pointers(
11+
void following_pointers( // $ ast-def=sourceStruct1_ptr
1212
int sourceArray1[],
1313
int cleanArray1[],
1414
twoIntFields sourceStruct1,

cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ postWithInFlow
107107
| test.cpp:552:25:552:25 | y [inner post update] | PostUpdateNode should not be the target of local flow. |
108108
| test.cpp:562:5:562:13 | globalInt [post update] | PostUpdateNode should not be the target of local flow. |
109109
| test.cpp:576:5:576:13 | globalInt [post update] | PostUpdateNode should not be the target of local flow. |
110+
| test.cpp:589:19:589:19 | x [inner post update] | PostUpdateNode should not be the target of local flow. |
110111
viableImplInCallContextTooLarge
111112
uniqueParameterNodeAtPosition
112113
uniqueParameterNodePosition

cpp/ql/test/library-tests/dataflow/dataflow-tests/dispatch.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ struct Bottom : Middle {
2525
void notSink(int x) override { }
2626
};
2727

28-
void VirtualDispatch(Bottom *bottomPtr, Bottom &bottomRef) {
28+
void VirtualDispatch(Bottom *bottomPtr, Bottom &bottomRef) { // $ ast-def=bottomPtr ast-def=bottomRef
2929
Top *topPtr = bottomPtr, &topRef = bottomRef;
3030

3131
sink(topPtr->isSource1()); // $ ir MISSING: ast
@@ -65,11 +65,11 @@ Top *allocateBottom() {
6565
return new Bottom();
6666
}
6767

68-
void callSinkByPointer(Top *top) {
68+
void callSinkByPointer(Top *top) { // $ ast-def=top
6969
top->isSink(source()); // leads to MISSING from ast
7070
}
7171

72-
void callSinkByReference(Top &top) {
72+
void callSinkByReference(Top &top) { // $ ast-def=top
7373
top.isSink(source()); // leads to MISSING from ast
7474
}
7575

@@ -81,11 +81,11 @@ void globalVirtualDispatch() {
8181
x->isSink(source()); // $ MISSING: ast,ir
8282
}
8383

84-
Top *identity(Top *top) {
84+
Top *identity(Top *top) { // $ ast-def=top
8585
return top;
8686
}
8787

88-
void callIdentityFunctions(Top *top, Bottom *bottom) {
88+
void callIdentityFunctions(Top *top, Bottom *bottom) { // $ ast-def=bottom ast-def=top
8989
identity(bottom)->isSink(source()); // $ MISSING: ast,ir
9090
identity(top)->isSink(source()); // no flow
9191
}
@@ -120,7 +120,7 @@ namespace virtual_inheritance {
120120
struct Bottom : Middle {
121121
};
122122

123-
void VirtualDispatch(Bottom *bottomPtr, Bottom &bottomRef) {
123+
void VirtualDispatch(Bottom *bottomPtr, Bottom &bottomRef) { // $ ast-def=bottomPtr ast-def=bottomRef
124124
// Because the inheritance from `Top` is virtual, the following casts go
125125
// directly from `Bottom` to `Top`, skipping `Middle`. That means we don't
126126
// get flow from a `Middle` value to the call qualifier.

cpp/ql/test/library-tests/dataflow/dataflow-tests/example.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ typedef struct
1212
char isTrue;
1313
} MyBool;
1414

15-
void myTest_with_local_flow(MyBool *b, int pos)
15+
void myTest_with_local_flow(MyBool *b, int pos) // $ ast-def=b
1616
{
1717
MyCoords coords = {0};
1818

cpp/ql/test/library-tests/dataflow/dataflow-tests/has-parameter-flow-out.expected

Whitespace-only changes.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import TestUtilities.InlineExpectationsTest
2+
import cpp
3+
4+
module AstTest {
5+
private import semmle.code.cpp.dataflow.old.DataFlow::DataFlow
6+
private import semmle.code.cpp.dataflow.old.internal.DataFlowPrivate
7+
8+
class ASTParameterDefTest extends InlineExpectationsTest {
9+
ASTParameterDefTest() { this = "ASTParameterDefTest" }
10+
11+
override string getARelevantTag() { result = "ast-def" }
12+
13+
override predicate hasActualResult(Location location, string element, string tag, string value) {
14+
exists(Function f, Parameter p, RefParameterFinalValueNode n |
15+
p.isNamed() and
16+
n.getParameter() = p and
17+
n.getFunction() = f and
18+
location = f.getLocation() and
19+
element = p.toString() and
20+
tag = "ast-def" and
21+
value = p.getName()
22+
)
23+
}
24+
}
25+
}
26+
27+
module IRTest {
28+
private import semmle.code.cpp.ir.dataflow.DataFlow
29+
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
30+
31+
class IRParameterDefTest extends InlineExpectationsTest {
32+
IRParameterDefTest() { this = "IRParameterDefTest" }
33+
34+
override string getARelevantTag() { result = "ir-def" }
35+
36+
override predicate hasActualResult(Location location, string element, string tag, string value) {
37+
exists(Function f, Parameter p, FinalParameterNode n |
38+
p.isNamed() and
39+
n.getParameter() = p and
40+
n.getFunction() = f and
41+
location = f.getLocation() and
42+
element = p.toString() and
43+
tag = "ir-def" and
44+
value = "**********".prefix(n.getIndirectionIndex()) + p.getName()
45+
)
46+
}
47+
}
48+
}

cpp/ql/test/library-tests/dataflow/dataflow-tests/lambdas.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ void test_lambdas()
3737
};
3838
d(t, u);
3939

40-
auto e = [](int &a, int &b, int &c) {
40+
auto e = [](int &a, int &b, int &c) { // $ ast-def=a ast-def=b ast-def=c ir-def=*c
4141
sink(a); // $ ast,ir
4242
sink(b);
4343
c = source();

cpp/ql/test/library-tests/dataflow/dataflow-tests/ref.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@ extern int arbitrary;
77

88
namespace withoutFields {
99
template<typename T>
10-
void assign(T &lhs, T rhs) {
10+
void assign(T &lhs, T rhs) { // $ ast-def=lhs ir-def=*lhs ast-def=lhs
1111
lhs = rhs;
1212
}
1313

1414
template<typename T>
15-
void assignWrapper(T &lhs, T rhs) {
15+
void assignWrapper(T &lhs, T rhs) { // $ ast-def=lhs ast-def=lhs
1616
assign(lhs, rhs);
1717
}
1818

19-
void notAssign(int &lhs, int rhs) {
19+
void notAssign(int &lhs, int rhs) { // $ ast-def=lhs ir-def=*lhs
2020
lhs = rhs;
2121
if (arbitrary) {
2222
lhs = 1;
@@ -25,22 +25,22 @@ namespace withoutFields {
2525
}
2626
}
2727

28-
void sourceToParam(int &out) {
28+
void sourceToParam(int &out) { // $ ast-def=out ir-def=*out
2929
out = source();
3030
if (arbitrary) {
3131
out = 1;
3232
}
3333
}
3434

35-
void sourceToParamWrapper(int &out) {
35+
void sourceToParamWrapper(int &out) { // $ ast-def=out ir-def=*out
3636
if (arbitrary) {
3737
sourceToParam(out);
3838
} else {
3939
out = 1;
4040
}
4141
}
4242

43-
void notSource(int &out) {
43+
void notSource(int &out) { // $ ast-def=out ir-def=*out
4444
out = source();
4545
if (arbitrary) {
4646
out = 1;
@@ -71,15 +71,15 @@ namespace withFields {
7171
int val;
7272
};
7373

74-
void assign(Int &lhs, int rhs) {
74+
void assign(Int &lhs, int rhs) { // $ ast-def=lhs
7575
lhs.val = rhs;
7676
}
7777

78-
void assignWrapper(Int &lhs, int rhs) {
78+
void assignWrapper(Int &lhs, int rhs) { // $ ast-def=lhs
7979
assign(lhs, rhs);
8080
}
8181

82-
void notAssign(Int &lhs, int rhs) {
82+
void notAssign(Int &lhs, int rhs) { // $ ast-def=lhs
8383
lhs.val = rhs;
8484
// Field flow ignores that the field is subsequently overwritten, leading
8585
// to false flow here.
@@ -90,22 +90,22 @@ namespace withFields {
9090
}
9191
}
9292

93-
void sourceToParam(Int &out) {
93+
void sourceToParam(Int &out) { // $ ast-def=out
9494
out.val = source();
9595
if (arbitrary) {
9696
out.val = 1;
9797
}
9898
}
9999

100-
void sourceToParamWrapper(Int &out) {
100+
void sourceToParamWrapper(Int &out) { // $ ast-def=out
101101
if (arbitrary) {
102102
sourceToParam(out);
103103
} else {
104104
out.val = 1;
105105
}
106106
}
107107

108-
void notSource(Int &out) {
108+
void notSource(Int &out) { // $ ast-def=out
109109
out.val = source();
110110
// Field flow ignores that the field is subsequently overwritten, leading
111111
// to false flow here.

cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ namespace std {
6363
template<class T> T&& move(T& t) noexcept; // simplified signature
6464
}
6565

66-
void identityOperations(int* source1) {
66+
void identityOperations(int* source1) { // $ ast-def=source1
6767
const int *x1 = std::move(source1);
6868
int* x2 = const_cast<int*>(x1);
6969
int* x3 = (x2);
@@ -86,7 +86,7 @@ void trackUninitialized() {
8686
sink(i1); // $ ast,ir
8787
}
8888

89-
void local_references(int &source1, int clean1) {
89+
void local_references(int &source1, int clean1) { // $ ast-def=source1 ir-def=*source1
9090
sink(source1); // $ ast,ir
9191
source1 = clean1;
9292
sink(source1); // clean
@@ -111,17 +111,17 @@ void local_references(int &source1, int clean1) {
111111
}
112112
}
113113

114-
int alwaysAssignSource(int *out) {
114+
int alwaysAssignSource(int *out) { // $ ast-def=out ir-def=*out
115115
*out = source();
116116
return 0;
117117
}
118118

119-
int alwaysAssign0(int *out) {
119+
int alwaysAssign0(int *out) { // $ ast-def=out ir-def=*out
120120
*out = 0;
121121
return 0;
122122
}
123123

124-
int alwaysAssignInput(int *out, int in) {
124+
int alwaysAssignInput(int *out, int in) { // $ ast-def=out ir-def=*out
125125
*out = in;
126126
return 0;
127127
}
@@ -468,7 +468,7 @@ void throughStmtExpr(int source1, int clean1) {
468468
sink(local); // $ ast,ir
469469
}
470470

471-
void intOutparamSource(int *p) {
471+
void intOutparamSource(int *p) { // $ ast-def=p ir-def=*p
472472
*p = source();
473473
}
474474

@@ -484,7 +484,7 @@ struct MyStruct {
484484
int* content;
485485
};
486486

487-
void local_field_flow_def_by_ref_steps_with_local_flow(MyStruct * s) {
487+
void local_field_flow_def_by_ref_steps_with_local_flow(MyStruct * s) { // $ ast-def=s
488488
writes_to_content(s->content);
489489
int* p_content = s->content;
490490
sink(*p_content);
@@ -502,7 +502,7 @@ void regression_with_phi_flow(int clean1) {
502502
}
503503
}
504504

505-
int intOutparamSourceMissingReturn(int *p) {
505+
int intOutparamSourceMissingReturn(int *p) { // $ ast-def=p ir-def=*p
506506
*p = source();
507507
// return deliberately omitted to test IR dataflow behavior
508508
}
@@ -521,23 +521,23 @@ void uncertain_definition() {
521521
sink(stackArray[0]); // $ ast=519:19 ir SPURIOUS: ast=517:7
522522
}
523523

524-
void set_through_const_pointer(int x, const int **e)
524+
void set_through_const_pointer(int x, const int **e) // $ ast-def=e ir-def=**e ir-def=*e
525525
{
526526
*e = &x;
527527
}
528528

529-
void test_set_through_const_pointer(int *e)
529+
void test_set_through_const_pointer(int *e) // $ ast-def=e
530530
{
531531
set_through_const_pointer(source(), &e);
532532
sink(*e); // $ ir MISSING: ast
533533
}
534534

535-
void sink_then_source_1(int* p) {
535+
void sink_then_source_1(int* p) { // $ ast-def=p ir-def=*p
536536
sink(*p); // $ ir // Flow from the unitialized x to the dereference.
537537
*p = source();
538538
}
539539

540-
void sink_then_source_2(int* p, int y) {
540+
void sink_then_source_2(int* p, int y) { // $ ast-def=p ir-def=*p
541541
sink(y); // $ SPURIOUS: ast ir
542542
*p = source();
543543
}
@@ -578,3 +578,14 @@ namespace IndirectFlowThroughGlobals {
578578
sink(*globalInt); // $ ir=562:17 ir=576:17 MISSING: ast=562:17 ast=576:17
579579
}
580580
}
581+
582+
void write_to_param(int* x) { // $ ast-def=x ir-def=*x
583+
int s = source();
584+
x = &s;
585+
}
586+
587+
void test_write_to_param() {
588+
int x = 0;
589+
write_to_param(&x);
590+
sink(x); // $ SPURIOUS: ast,ir
591+
}

0 commit comments

Comments
 (0)