Skip to content

Commit f5e320e

Browse files
author
Dave Bartolomeo
committed
Merge from master
2 parents 56cbd0c + d2f3574 commit f5e320e

File tree

298 files changed

+10488
-2959
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

298 files changed

+10488
-2959
lines changed

change-notes/1.23/analysis-java.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
The following changes in version 1.23 affect Java analysis in all applications.
44

5+
## New queries
6+
7+
| **Query** | **Tags** | **Purpose** |
8+
|-----------------------------|-----------|--------------------------------------------------------------------|
9+
| Continue statement that does not continue (`java/continue-in-false-loop`) | correctness | Finds `continue` statements in `do { ... } while (false)` loops. |
10+
511
## Changes to existing queries
612

713
| **Query** | **Expected impact** | **Change** |

change-notes/1.23/analysis-javascript.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,15 @@
1212

1313
* The call graph has been improved to resolve method calls in more cases. This may produce more security alerts.
1414

15+
* TypeScript 3.6 features are supported.
16+
17+
1518
## New queries
1619

1720
| **Query** | **Tags** | **Purpose** |
1821
|---------------------------------------------------------------------------|-------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
1922
| Unused index variable (`js/unused-index-variable`) | correctness | Highlights loops that iterate over an array, but do not use the index variable to access array elements, indicating a possible typo or logic error. Results are shown on LGTM by default. |
20-
| Loop bound injection (`js/loop-bound-injection`) | security, external/cwe/cwe-834 | Highlights loops where a user-controlled object with an arbitrary .length value can trick the server to loop indefinitely. Results are not shown on LGTM by default. |
23+
| Loop bound injection (`js/loop-bound-injection`) | security, external/cwe/cwe-834 | Highlights loops where a user-controlled object with an arbitrary .length value can trick the server to loop indefinitely. Results are shown on LGTM by default. |
2124
| Suspicious method name (`js/suspicious-method-name-declaration`) | correctness, typescript, methods | Highlights suspiciously named methods where the developer likely meant to write a constructor or function. Results are shown on LGTM by default. |
2225
| Shell command built from environment values (`js/shell-command-injection-from-environment`) | correctness, security, external/cwe/cwe-078, external/cwe/cwe-088 | Highlights shell commands that may change behavior inadvertently depending on the execution environment, indicating a possible violation of [CWE-78](https://cwe.mitre.org/data/definitions/78.html). Results are shown on LGTM by default.|
2326
| Use of returnless function (`js/use-of-returnless-function`) | maintainability, correctness | Highlights calls where the return value is used, but the callee never returns a value. Results are shown on LGTM by default. |

change-notes/1.23/analysis-python.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@
1919
| **Query** | **Expected impact** | **Change** |
2020
|----------------------------|------------------------|------------|
2121
| Unreachable code | Fewer false positives | Analysis now accounts for uses of `contextlib.suppress` to suppress exceptions. |
22-
22+
| `__iter__` method returns a non-iterator | Better alert message | Alert now highlights which class is expected to be an iterator. |

config/identical-files.json

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,11 @@
7676
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll",
7777
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll",
7878
"csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Operand.qll",
79-
"csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Operand.qll"
79+
"csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Operand.qll"
80+
],
81+
"IR IRType": [
82+
"cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll",
83+
"csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll"
8084
],
8185
"IR Operand Tag": [
8286
"cpp/ql/src/semmle/code/cpp/ir/implementation/internal/OperandTag.qll",
@@ -169,22 +173,39 @@
169173
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/PrintIRImports.qll",
170174
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/PrintIRImports.qll"
171175
],
176+
"C++ SSA SSAConstructionImports": [
177+
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstructionImports.qll",
178+
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstructionImports.qll"
179+
],
172180
"C++ SSA AliasAnalysis": [
173181
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll",
174182
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll"
175183
],
176-
"C++ SSA SSAConstruction": [
184+
"C++ IR ValueNumberingImports": [
185+
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingImports.qll",
186+
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingImports.qll",
187+
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/internal/ValueNumberingImports.qll"
188+
],
189+
"IR SSA SimpleSSA": [
190+
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll",
191+
"csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll"
192+
],
193+
"IR SSA SSAConstruction": [
177194
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll",
178-
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll"
195+
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll",
196+
"csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll"
179197
],
180-
"C++ SSA PrintSSA": [
198+
"IR SSA PrintSSA": [
181199
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/PrintSSA.qll",
182-
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/PrintSSA.qll"
200+
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/PrintSSA.qll",
201+
"csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/PrintSSA.qll"
183202
],
184-
"C++ IR ValueNumber": [
203+
"IR ValueNumber": [
185204
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/ValueNumbering.qll",
186205
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll",
187-
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/ValueNumbering.qll"
206+
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/ValueNumbering.qll",
207+
"csharp/ql/src/semmle/code/csharp/ir/implementation/raw/gvn/ValueNumbering.qll",
208+
"csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll"
188209
],
189210
"C++ IR ConstantAnalysis": [
190211
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/constant/ConstantAnalysis.qll",
@@ -235,5 +256,9 @@
235256
"C# IR PrintIRImports": [
236257
"csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/PrintIRImports.qll",
237258
"csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/PrintIRImports.qll"
259+
],
260+
"C# IR ValueNumberingImports": [
261+
"csharp/ql/src/semmle/code/csharp/ir/implementation/raw/gvn/internal/ValueNumberingImports.qll",
262+
"csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingImports.qll"
238263
]
239264
}

cpp/ql/src/Likely Bugs/Arithmetic/BadAdditionOverflowCheck.qhelp

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,39 @@
22
"-//Semmle//qhelp//EN"
33
"qhelp.dtd">
44
<qhelp>
5-
<overview>
6-
<p>
7-
Checking for overflow of integer addition needs to be done with
8-
care, because automatic type promotion can prevent the check
9-
from working correctly.
10-
</p>
11-
</overview>
12-
<recommendation>
13-
<p>
14-
Use an explicit cast to make sure that the result of the addition is
15-
not implicitly converted to a larger type.
16-
</p>
17-
</recommendation>
18-
<example>
19-
<sample src="BadAdditionOverflowCheckExample1.cpp" />
20-
<p>
21-
On a typical architecture where <tt>short</tt> is 16 bits
22-
and <tt>int</tt> is 32 bits, the operands of the addition are
23-
automatically promoted to <tt>int</tt>, so it cannot overflow
24-
and the result of the comparison is always false.
25-
</p>
26-
<p>
27-
The code below implements the check correctly, by using an
28-
explicit cast to make sure that the result of the addition
29-
is <tt>unsigned short</tt>.
30-
</p>
31-
<sample src="BadAdditionOverflowCheckExample2.cpp" />
32-
</example>
33-
<references>
34-
<li><a href="http://c-faq.com/expr/preservingrules.html">Preserving Rules</a></li>
35-
<li><a href="https://www.securecoding.cert.org/confluence/plugins/servlet/mobile#content/view/20086942">Understand integer conversion rules</a></li>
36-
</references>
5+
6+
<overview>
7+
<p>
8+
Checking for overflow of integer addition needs to be done with
9+
care, because automatic type promotion can prevent the check
10+
from working as intended, with the same value (<code>true</code>
11+
or <code>false</code>) always being returned.
12+
</p>
13+
</overview>
14+
<recommendation>
15+
<p>
16+
Use an explicit cast to make sure that the result of the addition is
17+
not implicitly converted to a larger type.
18+
</p>
19+
</recommendation>
20+
<example>
21+
<sample src="BadAdditionOverflowCheckExample1.cpp" />
22+
<p>
23+
On a typical architecture where <code>short</code> is 16 bits
24+
and <code>int</code> is 32 bits, the operands of the addition are
25+
automatically promoted to <code>int</code>, so it cannot overflow
26+
and the result of the comparison is always false.
27+
</p>
28+
<p>
29+
The code below implements the check correctly, by using an
30+
explicit cast to make sure that the result of the addition
31+
is <code>unsigned short</code> (which may overflow, in which case
32+
the comparison would evaluate to <code>true</code>).
33+
</p>
34+
<sample src="BadAdditionOverflowCheckExample2.cpp" />
35+
</example>
36+
<references>
37+
<li><a href="http://c-faq.com/expr/preservingrules.html">Preserving Rules</a></li>
38+
<li><a href="https://www.securecoding.cert.org/confluence/plugins/servlet/mobile#content/view/20086942">Understand integer conversion rules</a></li>
39+
</references>
3740
</qhelp>
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
bool checkOverflow(unsigned short x, unsigned short y) {
2-
return (x + y < x); // BAD: x and y are automatically promoted to int.
2+
// BAD: comparison is always false due to type promotion
3+
return (x + y < x);
34
}

cpp/ql/src/Likely Bugs/Arithmetic/ComparisonPrecedence.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@ where
1818
co.getAChild() = chco and
1919
not chco.isParenthesised() and
2020
not co.isFromUninstantiatedTemplate(_)
21-
select co, "Check the comparison operator precedence."
21+
select co, "Comparison as an operand to another comparison."
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
import cpp
2+
import semmle.code.cpp.dataflow.TaintTracking
3+
private import semmle.code.cpp.dataflow.RecursionPrevention
4+
5+
/**
6+
* A buffer which includes an allocation size.
7+
*/
8+
abstract class BufferWithSize extends DataFlow::Node {
9+
abstract Expr getSizeExpr();
10+
11+
BufferAccess getAnAccess() {
12+
any(BufferWithSizeConfig bsc).hasFlow(this, DataFlow::exprNode(result.getPointer()))
13+
}
14+
}
15+
16+
/** An allocation function. */
17+
abstract class Alloc extends Function { }
18+
19+
/**
20+
* Allocation functions identified by the QL for C/C++ standard library.
21+
*/
22+
class DefaultAlloc extends Alloc {
23+
DefaultAlloc() { allocationFunction(this) }
24+
}
25+
26+
/** A buffer created through a call to an allocation function. */
27+
class AllocBuffer extends BufferWithSize {
28+
FunctionCall call;
29+
30+
AllocBuffer() {
31+
asExpr() = call and
32+
call.getTarget() instanceof Alloc
33+
}
34+
35+
override Expr getSizeExpr() { result = call.getArgument(0) }
36+
}
37+
38+
/**
39+
* Find accesses of buffers for which we have a size expression.
40+
*/
41+
private class BufferWithSizeConfig extends TaintTracking::Configuration {
42+
BufferWithSizeConfig() { this = "BufferWithSize" }
43+
44+
override predicate isSource(DataFlow::Node n) { n = any(BufferWithSize b) }
45+
46+
override predicate isSink(DataFlow::Node n) { n.asExpr() = any(BufferAccess ae).getPointer() }
47+
48+
override predicate isSanitizer(DataFlow::Node s) {
49+
s = any(BufferWithSize b) and
50+
s.asExpr().getControlFlowScope() instanceof Alloc
51+
}
52+
}
53+
54+
/**
55+
* An access (read or write) to a buffer, provided as a pair of
56+
* a pointer to the buffer and the length of data to be read or written.
57+
* Extend this class to support different kinds of buffer access.
58+
*/
59+
abstract class BufferAccess extends Locatable {
60+
/** Gets the pointer to the buffer being accessed. */
61+
abstract Expr getPointer();
62+
63+
/** Gets the length of the data being read or written by this buffer access. */
64+
abstract Expr getAccessedLength();
65+
}
66+
67+
/**
68+
* A buffer access through an array expression.
69+
*/
70+
class ArrayBufferAccess extends BufferAccess, ArrayExpr {
71+
override Expr getPointer() { result = this.getArrayBase() }
72+
73+
override Expr getAccessedLength() { result = this.getArrayOffset() }
74+
}
75+
76+
/**
77+
* A buffer access through an overloaded array expression.
78+
*/
79+
class OverloadedArrayBufferAccess extends BufferAccess, OverloadedArrayExpr {
80+
override Expr getPointer() { result = this.getQualifier() }
81+
82+
override Expr getAccessedLength() { result = this.getAnArgument() }
83+
}
84+
85+
/**
86+
* A buffer access through pointer arithmetic.
87+
*/
88+
class PointerArithmeticAccess extends BufferAccess, Expr {
89+
PointerArithmeticOperation p;
90+
91+
PointerArithmeticAccess() {
92+
this = p and
93+
p.getAnOperand().getType().getUnspecifiedType() instanceof IntegralType and
94+
not p.getParent() instanceof ComparisonOperation
95+
}
96+
97+
override Expr getPointer() {
98+
result = p.getAnOperand() and
99+
result.getType().getUnspecifiedType() instanceof PointerType
100+
}
101+
102+
override Expr getAccessedLength() {
103+
result = p.getAnOperand() and
104+
result.getType().getUnspecifiedType() instanceof IntegralType
105+
}
106+
}
107+
108+
/**
109+
* A pair of buffer accesses through a call to memcpy.
110+
*/
111+
class MemCpy extends BufferAccess, FunctionCall {
112+
MemCpy() { getTarget().hasName("memcpy") }
113+
114+
override Expr getPointer() {
115+
result = getArgument(0) or
116+
result = getArgument(1)
117+
}
118+
119+
override Expr getAccessedLength() { result = getArgument(2) }
120+
}
121+
122+
class StrncpySizeExpr extends BufferAccess, FunctionCall {
123+
StrncpySizeExpr() { getTarget().hasName("strncpy") }
124+
125+
override Expr getPointer() {
126+
result = getArgument(0) or
127+
result = getArgument(1)
128+
}
129+
130+
override Expr getAccessedLength() { result = getArgument(2) }
131+
}
132+
133+
class RecvSizeExpr extends BufferAccess, FunctionCall {
134+
RecvSizeExpr() { getTarget().hasName("recv") }
135+
136+
override Expr getPointer() { result = getArgument(1) }
137+
138+
override Expr getAccessedLength() { result = getArgument(2) }
139+
}
140+
141+
class SendSizeExpr extends BufferAccess, FunctionCall {
142+
SendSizeExpr() { getTarget().hasName("send") }
143+
144+
override Expr getPointer() { result = getArgument(1) }
145+
146+
override Expr getAccessedLength() { result = getArgument(2) }
147+
}
148+
149+
class SnprintfSizeExpr extends BufferAccess, FunctionCall {
150+
SnprintfSizeExpr() { getTarget().hasName("snprintf") }
151+
152+
override Expr getPointer() { result = getArgument(0) }
153+
154+
override Expr getAccessedLength() { result = getArgument(1) }
155+
}
156+
157+
class MemcmpSizeExpr extends BufferAccess, FunctionCall {
158+
MemcmpSizeExpr() { getTarget().hasName("Memcmp") }
159+
160+
override Expr getPointer() {
161+
result = getArgument(0) or
162+
result = getArgument(1)
163+
}
164+
165+
override Expr getAccessedLength() { result = getArgument(2) }
166+
}
167+
168+
class MallocSizeExpr extends BufferAccess, FunctionCall {
169+
MallocSizeExpr() { getTarget().hasName("malloc") }
170+
171+
override Expr getPointer() { none() }
172+
173+
override Expr getAccessedLength() { result = getArgument(1) }
174+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
int get_number_from_network();
2+
3+
int process_network(int[] buff, int buffSize) {
4+
int i = ntohl(get_number_from_network());
5+
return buff[i];
6+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
uint32_t get_number_from_network();
2+
3+
int process_network(int[] buff, uint32_t buffSize) {
4+
uint32_t i = ntohl(get_number_from_network());
5+
if (i < buffSize) {
6+
return buff[i];
7+
} else {
8+
return -1;
9+
}
10+
}

0 commit comments

Comments
 (0)