Skip to content

Commit 8fc803f

Browse files
committed
Merge branch 'master' into python-keyword-only-args
2 parents f099e0f + 14664be commit 8fc803f

File tree

553 files changed

+19417
-6933
lines changed

Some content is hidden

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

553 files changed

+19417
-6933
lines changed

change-notes/1.25/analysis-cpp.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Improvements to C/C++ analysis
2+
3+
The following changes in version 1.25 affect C/C++ analysis in all applications.
4+
5+
## General improvements
6+
7+
## New queries
8+
9+
| **Query** | **Tags** | **Purpose** |
10+
|-----------------------------|-----------|--------------------------------------------------------------------|
11+
12+
## Changes to existing queries
13+
14+
| **Query** | **Expected impact** | **Change** |
15+
|----------------------------|------------------------|------------------------------------------------------------------|
16+
17+
## Changes to libraries
18+
19+
* The data-flow library has been improved, which affects most security queries by potentially
20+
adding more results. Flow through functions now takes nested field reads/writes into account.
21+
For example, the library is able to track flow from `taint()` to `sink()` via the method
22+
`getf2f1()` in
23+
```c
24+
struct C {
25+
int f1;
26+
};
27+
28+
struct C2
29+
{
30+
C f2;
31+
32+
int getf2f1() {
33+
return f2.f1; // Nested field read
34+
}
35+
36+
void m() {
37+
f2.f1 = taint();
38+
sink(getf2f1()); // NEW: taint() reaches here
39+
}
40+
};
41+
```

change-notes/1.25/analysis-csharp.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,28 @@ The following changes in version 1.25 affect C# analysis in all applications.
2424
have type parameters. This means that non-generic nested types inside construced types,
2525
such as `A<int>.B`, no longer are considered unbound generics. (Such nested types do,
2626
however, still have relevant `.getSourceDeclaration()`s, for example `A<>.B`.)
27+
* The data-flow library has been improved, which affects most security queries by potentially
28+
adding more results. Flow through methods now takes nested field reads/writes into account.
29+
For example, the library is able to track flow from `"taint"` to `Sink()` via the method
30+
`GetF2F1()` in
31+
```csharp
32+
class C1
33+
{
34+
string F1;
35+
}
36+
37+
class C2
38+
{
39+
C1 F2;
40+
41+
string GetF2F1() => F2.F1; // Nested field read
42+
43+
void M()
44+
{
45+
F2 = new C1() { F1 = "taint" };
46+
Sink(GetF2F1()); // NEW: "taint" reaches here
47+
}
48+
}
49+
```
2750

2851
## Changes to autobuilder

change-notes/1.25/analysis-java.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Improvements to Java analysis
2+
3+
The following changes in version 1.25 affect Java analysis in all applications.
4+
5+
## General improvements
6+
7+
## New queries
8+
9+
| **Query** | **Tags** | **Purpose** |
10+
|-----------------------------|-----------|--------------------------------------------------------------------|
11+
12+
13+
## Changes to existing queries
14+
15+
| **Query** | **Expected impact** | **Change** |
16+
|------------------------------|------------------------|-----------------------------------|
17+
18+
19+
## Changes to libraries
20+
21+
* The data-flow library has been improved, which affects most security queries by potentially
22+
adding more results. Flow through methods now takes nested field reads/writes into account.
23+
For example, the library is able to track flow from `"taint"` to `sink()` via the method
24+
`getF2F1()` in
25+
```java
26+
class C1 {
27+
String f1;
28+
C1(String f1) { this.f1 = f1; }
29+
}
30+
31+
class C2 {
32+
C1 f2;
33+
String getF2F1() {
34+
return this.f2.f1; // Nested field read
35+
}
36+
void m() {
37+
this.f2 = new C1("taint");
38+
sink(this.getF2F1()); // NEW: "taint" reaches here
39+
}
40+
}
41+
```

change-notes/1.25/analysis-javascript.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,20 @@
33
## General improvements
44

55
* Support for the following frameworks and libraries has been improved:
6+
- [express](https://www.npmjs.com/package/express)
7+
- [fstream](https://www.npmjs.com/package/fstream)
68
- [jGrowl](https://github.com/stanlemon/jGrowl)
79
- [jQuery](https://jquery.com/)
10+
- [marsdb](https://www.npmjs.com/package/marsdb)
11+
- [minimongo](https://www.npmjs.com/package/minimongo/)
812

913
## New queries
1014

1115
| **Query** | **Tags** | **Purpose** |
1216
|---------------------------------------------------------------------------------|-------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
1317
| Cross-site scripting through DOM (`js/xss-through-dom`) | security, external/cwe/cwe-079, external/cwe/cwe-116 | Highlights potential XSS vulnerabilities where existing text from the DOM is used as HTML. Results are not shown on LGTM by default. |
1418
| Incomplete HTML attribute sanitization (`js/incomplete-html-attribute-sanitization`) | security, external/cwe/cwe-20, external/cwe/cwe-079, external/cwe/cwe-116 | Highlights potential XSS vulnerabilities due to incomplete sanitization of HTML meta-characters. Results are shown on LGTM by default. |
19+
| Unsafe expansion of self-closing HTML tag (`js/unsafe-html-expansion`) | security, external/cwe/cwe-079, external/cwe/cwe-116 | Highlights potential XSS vulnerabilities caused by unsafe expansion of self-closing HTML tags. |
1520

1621
## Changes to existing queries
1722

@@ -20,8 +25,16 @@
2025
| Misspelled variable name (`js/misspelled-variable-name`) | Message changed | The message for this query now correctly identifies the misspelled variable in additional cases. |
2126
| Uncontrolled data used in path expression (`js/path-injection`) | More results | This query now recognizes additional file system calls. |
2227
| Uncontrolled command line (`js/command-line-injection`) | More results | This query now recognizes additional command execution calls. |
28+
| Client-side URL redirect (`js/client-side-unvalidated-url-redirection`) | Less results | This query now recognizes additional safe patterns of doing URL redirects. |
29+
| Client-side cross-site scripting (`js/xss`) | Less results | This query now recognizes additional safe strings based on URLs. |
30+
| Incomplete URL scheme check (`js/incomplete-url-scheme-check`) | More results | This query now recognizes additional url scheme checks. |
31+
| Prototype pollution in utility function (`js/prototype-pollution-utility`) | More results | This query now recognizes additional utility functions as vulnerable to prototype polution. |
2332
| Expression has no effect (`js/useless-expression`) | Less results | This query no longer flags an expression when that expression is the only content of the containing file. |
33+
| Unknown directive (`js/unknown-directive`) | Less results | This query no longer flags directives generated by the Babel compiler. |
34+
| Code injection (`js/code-injection`) | More results | More potential vulnerabilities involving NoSQL code operators are now recognized. |
35+
| Zip Slip (`js/zipslip`) | More results | This query now recognizes additional vulnerabilities. |
2436

2537
## Changes to libraries
2638

39+
* A library `semmle.javascript.explore.CallGraph` has been added to help write queries for exploring the call graph.
2740
* Added data flow for `Map` and `Set`, and added matching type-tracking steps that can accessed using the `CollectionsTypeTracking` module.

config/identical-files.json

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -111,12 +111,12 @@
111111
"csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IR.qll",
112112
"csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/IR.qll"
113113
],
114-
"IR IRSanity": [
115-
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRSanity.qll",
116-
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRSanity.qll",
117-
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRSanity.qll",
118-
"csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRSanity.qll",
119-
"csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/IRSanity.qll"
114+
"IR IRConsistency": [
115+
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRConsistency.qll",
116+
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRConsistency.qll",
117+
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRConsistency.qll",
118+
"csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRConsistency.qll",
119+
"csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/IRConsistency.qll"
120120
],
121121
"IR PrintIR": [
122122
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/PrintIR.qll",
@@ -157,10 +157,10 @@
157157
"cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll",
158158
"csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll"
159159
],
160-
"IR SSASanity": [
161-
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSASanity.qll",
162-
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSASanity.qll",
163-
"csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/SSASanity.qll"
160+
"IR SSAConsistency": [
161+
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConsistency.qll",
162+
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConsistency.qll",
163+
"csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/SSAConsistency.qll"
164164
],
165165
"C++ IR InstructionImports": [
166166
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/InstructionImports.qll",

cpp/ql/src/Documentation/CaptionedComments.qll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44

55
import cpp
66

7+
/**
8+
* Gets a string representation of the comment `c` containing the caption 'TODO' or 'FIXME'.
9+
* If `c` spans multiple lines, all lines after the first are abbreviated as [...].
10+
*/
711
string getCommentTextCaptioned(Comment c, string caption) {
812
(caption = "TODO" or caption = "FIXME") and
913
exists(

cpp/ql/src/Documentation/CommentedOutCode.qll

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
/**
2+
* Provides classes and predicates for identifying C/C++ comments that look like code.
3+
*/
4+
15
import cpp
26

37
/**
@@ -137,30 +141,52 @@ class CommentBlock extends Comment {
137141
)
138142
}
139143

144+
/**
145+
* Gets the last comment associated with this comment block.
146+
*/
140147
Comment lastComment() { result = this.getComment(max(int i | exists(this.getComment(i)))) }
141148

149+
/**
150+
* Gets the contents of the `i`'th comment associated with this comment block.
151+
*/
142152
string getLine(int i) {
143153
this instanceof CStyleComment and
144154
result = this.getContents().regexpCapture("(?s)/\\*+(.*)\\*+/", 1).splitAt("\n", i)
145155
or
146156
this instanceof CppStyleComment and result = this.getComment(i).getContents().suffix(2)
147157
}
148158

159+
/**
160+
* Gets the number of lines in the comments associated with this comment block.
161+
*/
149162
int numLines() {
150163
result = strictcount(int i, string line | line = this.getLine(i) and line.trim() != "")
151164
}
152165

166+
/**
167+
* Gets the number of lines that look like code in the comments associated with this comment block.
168+
*/
153169
int numCodeLines() {
154170
result = strictcount(int i, string line | line = this.getLine(i) and looksLikeCode(line))
155171
}
156172

173+
/**
174+
* Holds if the comment block is a C-style comment, and each
175+
* comment line starts with a *.
176+
*/
157177
predicate isDocumentation() {
158178
// If a C-style comment starts each line with a *, then it's
159179
// probably documentation rather than code.
160180
this instanceof CStyleComment and
161181
forex(int i | i in [1 .. this.numLines() - 1] | this.getLine(i).trim().matches("*%"))
162182
}
163183

184+
/**
185+
* Holds if this comment block looks like code that has been commented out. Specifically:
186+
* 1. It does not look like documentation (see `isDocumentation`).
187+
* 2. It is not in a header file without any declaration entries or top level declarations.
188+
* 3. More than half of the lines in the comment block look like code.
189+
*/
164190
predicate isCommentedOutCode() {
165191
not this.isDocumentation() and
166192
not this.getFile().(HeaderFile).noTopLevelCode() and

cpp/ql/src/codeql-suites/cpp-lgtm-full.qls

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,8 @@
1212
- Critical/FileNeverClosed.ql
1313
- Critical/MemoryMayNotBeFreed.ql
1414
- Critical/MemoryNeverFreed.ql
15+
# These are only for IDE use.
16+
- exclude:
17+
tags contain:
18+
- ide-contextual-queries/local-definitions
19+
- ide-contextual-queries/local-references

cpp/ql/src/definitions.qll

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ private predicate constructorCallTypeMention(ConstructorCall cc, TypeMention tm)
132132
* - `"X"` for macro accesses
133133
* - `"I"` for import / include directives
134134
*/
135+
cached
135136
Top definitionOf(Top e, string kind) {
136137
(
137138
// call -> function called
@@ -213,3 +214,11 @@ Top definitionOf(Top e, string kind) {
213214
// later on.
214215
strictcount(result.getLocation()) < 10
215216
}
217+
218+
/**
219+
* Returns an appropriately encoded version of a filename `name`
220+
* passed by the VS Code extension in order to coincide with the
221+
* output of `.getFile()` on locatable entities.
222+
*/
223+
cached
224+
File getEncodedFile(string name) { result.getAbsolutePath().replaceAll(":", "_") = name }
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/**
2+
* This library proves that a subset of pointer dereferences in a program are
3+
* safe, i.e. in-bounds.
4+
* It does so by first defining what a pointer dereference is (on the IR
5+
* `Instruction` level), and then using the array length analysis and the range
6+
* analysis together to prove that some of these pointer dereferences are safe.
7+
*
8+
* The analysis is soundy, i.e. it is sound if no undefined behaviour is present
9+
* in the program.
10+
* Furthermore, it crucially depends on the soundiness of the range analysis and
11+
* the array length analysis.
12+
*/
13+
14+
import cpp
15+
private import experimental.semmle.code.cpp.rangeanalysis.ArrayLengthAnalysis
16+
private import semmle.code.cpp.rangeanalysis.RangeAnalysis
17+
18+
/**
19+
* Gets the instruction that computes the address of memory that `i` accesses.
20+
* Only holds if `i` dereferences a pointer, not when the computation of the
21+
* memory address is constant, or if the address of a local variable is loaded/stored to.
22+
*/
23+
private Instruction getMemoryAddressInstruction(Instruction i) {
24+
(
25+
result = i.(FieldAddressInstruction).getObjectAddress() or
26+
result = i.(LoadInstruction).getSourceAddress() or
27+
result = i.(StoreInstruction).getDestinationAddress()
28+
) and
29+
not result instanceof FieldAddressInstruction and
30+
not result instanceof VariableAddressInstruction and
31+
not result instanceof ConstantValueInstruction
32+
}
33+
34+
/**
35+
* All instructions that dereference a pointer.
36+
*/
37+
class PointerDereferenceInstruction extends Instruction {
38+
PointerDereferenceInstruction() { exists(getMemoryAddressInstruction(this)) }
39+
40+
Instruction getAddress() { result = getMemoryAddressInstruction(this) }
41+
}
42+
43+
/**
44+
* Holds if `ptrDeref` can be proven to always access allocated memory.
45+
*/
46+
predicate inBounds(PointerDereferenceInstruction ptrDeref) {
47+
exists(Length length, int lengthDelta, Offset offset, int offsetDelta |
48+
knownArrayLength(ptrDeref.getAddress(), length, lengthDelta, offset, offsetDelta) and
49+
// lower bound - note that we treat a pointer that accesses an array of
50+
// length 0 as on upper-bound violation, but not as a lower-bound violation
51+
(
52+
offset instanceof ZeroOffset and
53+
offsetDelta >= 0
54+
or
55+
offset instanceof OpOffset and
56+
exists(int lowerBoundDelta |
57+
boundedOperand(offset.(OpOffset).getOperand(), any(ZeroBound b), lowerBoundDelta,
58+
/*upper*/ false, _) and
59+
lowerBoundDelta + offsetDelta >= 0
60+
)
61+
) and
62+
// upper bound
63+
(
64+
// both offset and length are only integers
65+
length instanceof ZeroLength and
66+
offset instanceof ZeroOffset and
67+
offsetDelta < lengthDelta
68+
or
69+
exists(int lengthBound |
70+
// array length is variable+integer, and there's a fixed (integer-only)
71+
// lower bound on the variable, so we can guarantee this access is always in-bounds
72+
length instanceof VNLength and
73+
offset instanceof ZeroOffset and
74+
boundedInstruction(length.(VNLength).getInstruction(), any(ZeroBound b), lengthBound,
75+
/* upper*/ false, _) and
76+
offsetDelta < lengthBound + lengthDelta
77+
)
78+
or
79+
exists(int offsetBoundDelta |
80+
length instanceof ZeroLength and
81+
offset instanceof OpOffset and
82+
boundedOperand(offset.(OpOffset).getOperand(), any(ZeroBound b), offsetBoundDelta,
83+
/* upper */ true, _) and
84+
// offset <= offsetBoundDelta, so offset + offsetDelta <= offsetDelta + offsetBoundDelta
85+
// Thus, in-bounds if offsetDelta + offsetBoundDelta < lengthDelta
86+
// as we have length instanceof ZeroLength
87+
offsetDelta + offsetBoundDelta < lengthDelta
88+
)
89+
or
90+
exists(ValueNumberBound b, int offsetBoundDelta |
91+
length instanceof VNLength and
92+
offset instanceof OpOffset and
93+
b.getValueNumber() = length.(VNLength).getValueNumber() and
94+
// It holds that offset <= length + offsetBoundDelta
95+
boundedOperand(offset.(OpOffset).getOperand(), b, offsetBoundDelta, /*upper*/ true, _) and
96+
// it also holds that
97+
offsetDelta < lengthDelta - offsetBoundDelta
98+
// taking both inequalities together we get
99+
// offset <= length + offsetBoundDelta
100+
// => offset + offsetDelta <= length + offsetBoundDelta + offsetDelta < length + offsetBoundDelta + lengthDelta - offsetBoundDelta
101+
// as required
102+
)
103+
)
104+
)
105+
}

0 commit comments

Comments
 (0)