Skip to content

Commit 208b85c

Browse files
committed
Merge branch 'main' into mathiasvp/read-step-without-memory-operands
2 parents ed7e499 + eea8934 commit 208b85c

File tree

11 files changed

+368
-33
lines changed

11 files changed

+368
-33
lines changed

change-notes/1.26/analysis-cpp.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ The following changes in version 1.26 affect C/C++ analysis in all applications.
1313

1414
| **Query** | **Expected impact** | **Change** |
1515
|----------------------------|------------------------|------------------------------------------------------------------|
16+
| Declaration hides parameter (`cpp/declaration-hides-parameter`) | Fewer false positive results | False positives involving template functions have been fixed. |
1617
| Inconsistent direction of for loop (`cpp/inconsistent-loop-direction`) | Fewer false positive results | The query now accounts for intentional wrapping of an unsigned loop counter. |
1718
| Overflow in uncontrolled allocation size (`cpp/uncontrolled-allocation-size`) | | The precision of this query has been decreased from "high" to "medium". As a result, the query is still run but results are no longer displayed on LGTM by default. |
1819
| Comparison result is always the same (`cpp/constant-comparison`) | More correct results | Bounds on expressions involving multiplication can now be determined in more cases. |

cpp/ql/src/Best Practices/Hiding/DeclarationHidesParameter.ql

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,35 @@
1111

1212
import cpp
1313

14+
/**
15+
* Gets the template that a function `f` is constructed from, or just `f` if it
16+
* is not from a template instantiation.
17+
*/
18+
Function getConstructedFrom(Function f) {
19+
f.isConstructedFrom(result)
20+
or
21+
not f.isConstructedFrom(_) and
22+
result = f
23+
}
24+
1425
/**
1526
* Gets the parameter of `f` with name `name`, which has to come from the
1627
* _definition_ of `f` and not a prototype declaration.
1728
* We also exclude names from functions that have multiple definitions.
1829
* This should not happen in a single application but since we
1930
* have a system wide view it is likely to happen for instance for
2031
* the main function.
32+
*
33+
* Note: we use `getConstructedFrom` to ensure that we look at template
34+
* functions rather than their instantiations. We get better results this way
35+
* as the instantiation is artificial and may have inherited parameter names
36+
* from the declaration rather than the definition.
2137
*/
2238
ParameterDeclarationEntry functionParameterNames(Function f, string name) {
2339
exists(FunctionDeclarationEntry fe |
2440
result.getFunctionDeclarationEntry() = fe and
25-
fe.getFunction() = f and
41+
getConstructedFrom(f).getDefinition() = fe and
2642
fe.getLocation() = f.getDefinitionLocation() and
27-
result.getFile() = fe.getFile() and // Work around CPP-331
2843
strictcount(f.getDefinitionLocation()) = 1 and
2944
result.getName() = name
3045
)

cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* Provides implementation classes modeling `std::string` and other
3-
* instantiations of`std::basic_string`. See `semmle.code.cpp.models.Models`
3+
* instantiations of `std::basic_string`. See `semmle.code.cpp.models.Models`
44
* for usage information.
55
*/
66

@@ -82,6 +82,32 @@ class StdStringData extends TaintFunction {
8282
}
8383
}
8484

85+
/**
86+
* The `std::string` function `push_back`.
87+
*/
88+
class StdStringPush extends TaintFunction {
89+
StdStringPush() { this.hasQualifiedName("std", "basic_string", "push_back") }
90+
91+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
92+
// flow from parameter to qualifier
93+
input.isParameterDeref(0) and
94+
output.isQualifierObject()
95+
}
96+
}
97+
98+
/**
99+
* The `std::string` functions `front` and `back`.
100+
*/
101+
class StdStringFrontBack extends TaintFunction {
102+
StdStringFrontBack() { this.hasQualifiedName("std", "basic_string", ["front", "back"]) }
103+
104+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
105+
// flow from object to returned reference
106+
input.isQualifierObject() and
107+
output.isReturnValueDeref()
108+
}
109+
}
110+
85111
/**
86112
* The `std::string` function `operator+`.
87113
*/
@@ -138,6 +164,11 @@ class StdStringAppend extends TaintFunction {
138164
output.isQualifierObject() or
139165
output.isReturnValueDeref()
140166
)
167+
or
168+
// reverse flow from returned reference to the qualifier (for writes to
169+
// the result)
170+
input.isReturnValueDeref() and
171+
output.isQualifierObject()
141172
}
142173
}
143174

@@ -173,6 +204,11 @@ class StdStringAssign extends TaintFunction {
173204
output.isQualifierObject() or
174205
output.isReturnValueDeref()
175206
)
207+
or
208+
// reverse flow from returned reference to the qualifier (for writes to
209+
// the result)
210+
input.isReturnValueDeref() and
211+
output.isQualifierObject()
176212
}
177213
}
178214

cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected

Lines changed: 142 additions & 23 deletions
Large diffs are not rendered by default.

cpp/ql/test/library-tests/dataflow/taint-tests/stl.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,13 @@ namespace std
9191
const_iterator cbegin() const;
9292
const_iterator cend() const;
9393

94+
void push_back(charT c);
95+
96+
const charT& front() const;
97+
charT& front();
98+
const charT& back() const;
99+
charT& back();
100+
94101
const_reference operator[](size_type pos) const;
95102
reference operator[](size_type pos);
96103
const_reference at(size_type n) const;

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

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,12 +158,12 @@ void test_string_append() {
158158
sink(s5); // tainted
159159

160160
s6 = s3;
161-
s6 += s4;
161+
sink(s6 += s4); // tainted
162162
sink(s6); // tainted
163163

164164
s7 = s3;
165-
s7 += source();
166-
s7 += " ";
165+
sink(s7 += source()); // tainted
166+
sink(s7 += " "); // tainted
167167
sink(s7); // tainted
168168

169169
s8 = s3;
@@ -505,3 +505,55 @@ void test_constructors_more() {
505505
sink(s3);
506506
sink(s4); // tainted
507507
}
508+
509+
void test_string_front_back() {
510+
std::string a("aa");
511+
512+
sink(a.front());
513+
sink(a.back());
514+
a.push_back(ns_char::source());
515+
sink(a.front()); // [FALSE POSITIVE]
516+
sink(a.back()); // tainted
517+
}
518+
519+
void test_string_return_assign() {
520+
{
521+
std::string a("aa");
522+
std::string b("bb");
523+
std::string c("cc");
524+
std::string d("dd");
525+
std::string e("ee");
526+
std::string f("ff");
527+
528+
sink( a += (b += "bb") );
529+
sink( c += (d += source()) ); // tainted
530+
sink( (e += "ee") += source() ); // tainted
531+
sink( (f += source()) += "ff" ); // tainted
532+
sink(a);
533+
sink(b);
534+
sink(c); // tainted
535+
sink(d); // tainted
536+
sink(e); // tainted
537+
sink(f); // tainted
538+
}
539+
540+
{
541+
std::string a("aa");
542+
std::string b("bb");
543+
std::string c("cc");
544+
std::string d("dd");
545+
std::string e("ee");
546+
std::string f("ff");
547+
548+
sink( a.assign(b.assign("bb")) );
549+
sink( c.assign(d.assign(source())) ); // tainted
550+
sink( e.assign("ee").assign(source()) ); // tainted
551+
sink( f.assign(source()).assign("ff") );
552+
sink(a);
553+
sink(b);
554+
sink(c); // tainted
555+
sink(d); // tainted
556+
sink(e); // tainted
557+
sink(f); // [FALSE POSITIVE]
558+
}
559+
}

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

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,11 @@
6767
| string.cpp:146:11:146:11 | call to operator+ | string.cpp:141:18:141:23 | call to source |
6868
| string.cpp:149:11:149:11 | call to operator+ | string.cpp:149:13:149:18 | call to source |
6969
| string.cpp:158:8:158:9 | s5 | string.cpp:154:18:154:23 | call to source |
70+
| string.cpp:161:11:161:11 | call to operator+= | string.cpp:154:18:154:23 | call to source |
7071
| string.cpp:162:8:162:9 | s6 | string.cpp:154:18:154:23 | call to source |
71-
| string.cpp:167:8:167:9 | s7 | string.cpp:165:9:165:14 | call to source |
72+
| string.cpp:165:11:165:11 | call to operator+= | string.cpp:165:14:165:19 | call to source |
73+
| string.cpp:166:11:166:11 | call to operator+= | string.cpp:165:14:165:19 | call to source |
74+
| string.cpp:167:8:167:9 | s7 | string.cpp:165:14:165:19 | call to source |
7275
| string.cpp:171:8:171:9 | s8 | string.cpp:154:18:154:23 | call to source |
7376
| string.cpp:176:8:176:9 | s9 | string.cpp:174:13:174:18 | call to source |
7477
| string.cpp:184:8:184:10 | s10 | string.cpp:181:12:181:26 | call to source |
@@ -138,6 +141,21 @@
138141
| string.cpp:491:8:491:9 | s6 | string.cpp:482:18:482:23 | call to source |
139142
| string.cpp:504:7:504:8 | s2 | string.cpp:497:14:497:19 | call to source |
140143
| string.cpp:506:7:506:8 | s4 | string.cpp:497:14:497:19 | call to source |
144+
| string.cpp:515:9:515:13 | call to front | string.cpp:514:14:514:28 | call to source |
145+
| string.cpp:516:9:516:12 | call to back | string.cpp:514:14:514:28 | call to source |
146+
| string.cpp:529:11:529:11 | call to operator+= | string.cpp:529:20:529:25 | call to source |
147+
| string.cpp:530:21:530:21 | call to operator+= | string.cpp:530:24:530:29 | call to source |
148+
| string.cpp:531:25:531:25 | call to operator+= | string.cpp:531:15:531:20 | call to source |
149+
| string.cpp:534:8:534:8 | c | string.cpp:529:20:529:25 | call to source |
150+
| string.cpp:535:8:535:8 | d | string.cpp:529:20:529:25 | call to source |
151+
| string.cpp:536:8:536:8 | e | string.cpp:530:24:530:29 | call to source |
152+
| string.cpp:537:8:537:8 | f | string.cpp:531:15:531:20 | call to source |
153+
| string.cpp:549:11:549:16 | call to assign | string.cpp:549:27:549:32 | call to source |
154+
| string.cpp:550:24:550:29 | call to assign | string.cpp:550:31:550:36 | call to source |
155+
| string.cpp:554:8:554:8 | c | string.cpp:549:27:549:32 | call to source |
156+
| string.cpp:555:8:555:8 | d | string.cpp:549:27:549:32 | call to source |
157+
| string.cpp:556:8:556:8 | e | string.cpp:550:31:550:36 | call to source |
158+
| string.cpp:557:8:557:8 | f | string.cpp:551:18:551:23 | call to source |
141159
| structlikeclass.cpp:35:8:35:9 | s1 | structlikeclass.cpp:29:22:29:27 | call to source |
142160
| structlikeclass.cpp:36:8:36:9 | s2 | structlikeclass.cpp:30:24:30:29 | call to source |
143161
| structlikeclass.cpp:37:8:37:9 | s3 | structlikeclass.cpp:29:22:29:27 | call to source |

cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,11 @@
6767
| string.cpp:146:11:146:11 | string.cpp:141:18:141:23 | AST only |
6868
| string.cpp:149:11:149:11 | string.cpp:149:13:149:18 | AST only |
6969
| string.cpp:158:8:158:9 | string.cpp:154:18:154:23 | AST only |
70+
| string.cpp:161:11:161:11 | string.cpp:154:18:154:23 | AST only |
7071
| string.cpp:162:8:162:9 | string.cpp:154:18:154:23 | AST only |
71-
| string.cpp:167:8:167:9 | string.cpp:165:9:165:14 | AST only |
72+
| string.cpp:165:11:165:11 | string.cpp:165:14:165:19 | AST only |
73+
| string.cpp:166:11:166:11 | string.cpp:165:14:165:19 | AST only |
74+
| string.cpp:167:8:167:9 | string.cpp:165:14:165:19 | AST only |
7275
| string.cpp:171:8:171:9 | string.cpp:154:18:154:23 | AST only |
7376
| string.cpp:176:8:176:9 | string.cpp:174:13:174:18 | AST only |
7477
| string.cpp:184:8:184:10 | string.cpp:181:12:181:26 | AST only |
@@ -138,6 +141,21 @@
138141
| string.cpp:491:8:491:9 | string.cpp:482:18:482:23 | AST only |
139142
| string.cpp:504:7:504:8 | string.cpp:497:14:497:19 | AST only |
140143
| string.cpp:506:7:506:8 | string.cpp:497:14:497:19 | AST only |
144+
| string.cpp:515:9:515:13 | string.cpp:514:14:514:28 | AST only |
145+
| string.cpp:516:9:516:12 | string.cpp:514:14:514:28 | AST only |
146+
| string.cpp:529:11:529:11 | string.cpp:529:20:529:25 | AST only |
147+
| string.cpp:530:21:530:21 | string.cpp:530:24:530:29 | AST only |
148+
| string.cpp:531:25:531:25 | string.cpp:531:15:531:20 | AST only |
149+
| string.cpp:534:8:534:8 | string.cpp:529:20:529:25 | AST only |
150+
| string.cpp:535:8:535:8 | string.cpp:529:20:529:25 | AST only |
151+
| string.cpp:536:8:536:8 | string.cpp:530:24:530:29 | AST only |
152+
| string.cpp:537:8:537:8 | string.cpp:531:15:531:20 | AST only |
153+
| string.cpp:549:11:549:16 | string.cpp:549:27:549:32 | AST only |
154+
| string.cpp:550:24:550:29 | string.cpp:550:31:550:36 | AST only |
155+
| string.cpp:554:8:554:8 | string.cpp:549:27:549:32 | AST only |
156+
| string.cpp:555:8:555:8 | string.cpp:549:27:549:32 | AST only |
157+
| string.cpp:556:8:556:8 | string.cpp:550:31:550:36 | AST only |
158+
| string.cpp:557:8:557:8 | string.cpp:551:18:551:23 | AST only |
141159
| swap1.cpp:78:12:78:16 | swap1.cpp:69:23:69:23 | AST only |
142160
| swap1.cpp:87:13:87:17 | swap1.cpp:82:16:82:21 | AST only |
143161
| swap1.cpp:88:13:88:17 | swap1.cpp:81:27:81:28 | AST only |
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,7 @@
11
| hiding.cpp:4:17:4:18 | ii | Local variable 'ii' hides a $@. | hiding.cpp:2:12:2:13 | definition of ii | parameter of the same name |
22
| hiding.cpp:15:15:15:16 | kk | Local variable 'kk' hides a $@. | hiding.cpp:12:25:12:26 | definition of kk | parameter of the same name |
3+
| hiding.cpp:28:7:28:7 | a | Local variable 'a' hides a $@. | hiding.cpp:26:21:26:21 | definition of a | parameter of the same name |
4+
| hiding.cpp:45:7:45:7 | a | Local variable 'a' hides a $@. | hiding.cpp:43:41:43:41 | definition of a | parameter of the same name |
5+
| hiding.cpp:64:11:64:11 | i | Local variable 'i' hides a $@. | hiding.cpp:61:20:61:20 | definition of i | parameter of the same name |
6+
| hiding.cpp:78:7:78:10 | arg1 | Local variable 'arg1' hides a $@. | hiding.cpp:74:28:74:31 | definition of arg1 | parameter of the same name |
7+
| hiding.cpp:79:5:79:8 | arg2 | Local variable 'arg2' hides a $@. | hiding.cpp:74:36:74:39 | definition of arg2 | parameter of the same name |

cpp/ql/test/query-tests/Best Practices/Hiding/DeclarationHidesParameter/hiding.cpp

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
void f(int ii) {
33
if (1) {
4-
for(int ii = 1; ii < 10; ii++) {
4+
for(int ii = 1; ii < 10; ii++) { // local variable hides parameter of the same name
55
;
66
}
77
}
@@ -12,7 +12,7 @@ namespace foo {
1212
void f2(int ii, int kk) {
1313
try {
1414
for (ii = 0; ii < 3; ii++) {
15-
int kk;
15+
int kk; // local variable hides parameter of the same name
1616
}
1717
}
1818
catch (int ee) {
@@ -21,4 +21,61 @@ namespace foo {
2121
}
2222
}
2323

24+
void myFunction(int a, int b, int c);
2425

26+
void myFunction(int a, int b, int _c) {
27+
{
28+
int a = a; // local variable hides parameter of the same name
29+
int _b = b;
30+
int c = _c;
31+
32+
// ...
33+
}
34+
}
35+
36+
template<class T>
37+
class MyTemplateClass {
38+
public:
39+
void myMethod(int a, int b, int c);
40+
};
41+
42+
template<class T>
43+
void MyTemplateClass<T> :: myMethod(int a, int b, int _c) {
44+
{
45+
int a = a; // local variable hides parameter of the same name
46+
int _b = b;
47+
int c = _c;
48+
49+
// ...
50+
}
51+
}
52+
53+
MyTemplateClass<int> mtc_i;
54+
55+
void test() {
56+
mtc_i.myMethod(0, 0, 0);
57+
}
58+
59+
#define MYMACRO for (int i = 0; i < 10; i++) {}
60+
61+
void testMacro(int i) {
62+
MYMACRO;
63+
64+
for (int i = 0; i < 10; i++) {}; // local variable hides parameter of the same name
65+
}
66+
67+
#include "hiding.h"
68+
69+
void myClass::myCaller(void) {
70+
this->myMethod(5, 6);
71+
}
72+
73+
template <typename T>
74+
void myClass::myMethod(int arg1, T arg2) {
75+
{
76+
int protoArg1;
77+
T protoArg2;
78+
int arg1; // local variable hides parameter of the same name
79+
T arg2; // local variable hides parameter of the same name
80+
}
81+
}

0 commit comments

Comments
 (0)