Skip to content

Commit cdfcee3

Browse files
committed
Merge remote-tracking branch 'upstream/master' into ir-crement-load
Conflicts: cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected
2 parents 036e16a + 163285b commit cdfcee3

File tree

296 files changed

+11280
-2382
lines changed

Some content is hidden

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

296 files changed

+11280
-2382
lines changed

change-notes/1.24/analysis-cpp.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ The following changes in version 1.24 affect C/C++ analysis in all applications.
2626

2727
## Changes to libraries
2828

29+
* The data-flow library has been improved when flow through functions needs to be
30+
combined with both taint tracking and flow through fields allowing more flow
31+
to be tracked. This affects and improves some security queries, which may
32+
report additional results.
2933
* Created the `semmle.code.cpp.models.interfaces.Allocation` library to model allocation such as `new` expressions and calls to `malloc`. This in intended to replace the functionality in `semmle.code.cpp.commons.Alloc` with a more consistent and useful interface.
3034
* Created the `semmle.code.cpp.models.interfaces.Deallocation` library to model deallocation such as `delete` expressions and calls to `free`. This in intended to replace the functionality in `semmle.code.cpp.commons.Alloc` with a more consistent and useful interface.
3135
* The new class `StackVariable` should be used in place of `LocalScopeVariable`

change-notes/1.24/analysis-csharp.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ The following changes in version 1.24 affect C# analysis in all applications.
1818
| **Query** | **Expected impact** | **Change** |
1919
|------------------------------|------------------------|-----------------------------------|
2020
| Useless assignment to local variable (`cs/useless-assignment-to-local`) | Fewer false positive results | Results have been removed when the variable is named `_` in a `foreach` statement. |
21+
| Potentially dangerous use of non-short-circuit logic (`cs/non-short-circuit`) | Fewer false positive results | Results have been removed when the expression contains an `out` parameter. |
2122
| Dereferenced variable may be null (`cs/dereferenced-value-may-be-null`) | More results | Results are reported from parameters with a default value of `null`. |
2223

2324
## Removal of old queries
@@ -29,6 +30,10 @@ The following changes in version 1.24 affect C# analysis in all applications.
2930

3031
## Changes to libraries
3132

33+
* The data-flow library has been improved when flow through methods needs to be
34+
combined with both taint tracking and flow through fields allowing more flow
35+
to be tracked. This affects and improves most security queries, which may
36+
report additional results.
3237
* The taint tracking library now tracks flow through (implicit or explicit) conversion operator calls.
3338
* [Code contracts](https://docs.microsoft.com/en-us/dotnet/framework/debug-trace-profile/code-contracts) are now recognized, and are treated like any other assertion methods.
3439
* Expression nullability flow state is given by the predicates `Expr.hasNotNullFlowState()` and `Expr.hasMaybeNullFlowState()`.

change-notes/1.24/analysis-java.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@ The following changes in version 1.24 affect Java analysis in all applications.
1010

1111
| **Query** | **Tags** | **Purpose** |
1212
|-----------------------------|-----------|--------------------------------------------------------------------|
13-
| Disabled Spring CSRF protection (`java/spring-disabled-csrf-protection`) | security, external/cwe/cwe-352 | Finds disabled Cross-Site Request Forgery (CSRF) protection in Spring. |
13+
| Disabled Spring CSRF protection (`java/spring-disabled-csrf-protection`) | security, external/cwe/cwe-352 | Finds disabled Cross-Site Request Forgery (CSRF) protection in Spring. Results are shown on LGTM by default. |
1414
| Failure to use HTTPS or SFTP URL in Maven artifact upload/download (`java/maven/non-https-url`) | security, external/cwe/cwe-300, external/cwe/cwe-319, external/cwe/cwe-494, external/cwe/cwe-829 | Finds use of insecure protocols during Maven dependency resolution. Results are shown on LGTM by default. |
15+
| LDAP query built from user-controlled sources (`java/ldap-injection`) | security, external/cwe/cwe-090 | Finds LDAP queries vulnerable to injection of unsanitized user-controlled input. Results are shown on LGTM by default. |
1516
| Left shift by more than the type width (`java/lshift-larger-than-type-width`) | correctness | Finds left shifts of ints by 32 bits or more and left shifts of longs by 64 bits or more. Results are shown on LGTM by default. |
16-
| Suspicious date format (`java/suspicious-date-format`) | correctness | Finds date format patterns that use placeholders that are likely to be incorrect. |
17+
| Suspicious date format (`java/suspicious-date-format`) | correctness | Finds date format patterns that use placeholders that are likely to be incorrect. Results are shown on LGTM by default. |
1718

1819
## Changes to existing queries
1920

@@ -25,10 +26,17 @@ The following changes in version 1.24 affect Java analysis in all applications.
2526

2627
## Changes to libraries
2728

29+
* The data-flow library has been improved when flow through methods needs to be
30+
combined with both taint tracking and flow through fields allowing more flow
31+
to be tracked. This affects and improves most security queries, which may
32+
report additional results.
2833
* Identification of test classes has been improved. Previously, one of the
2934
match conditions would classify any class with a name containing the string
3035
"Test" as a test class, but now this matching has been replaced with one that
3136
looks for the occurrence of actual unit-test annotations. This affects the
3237
general file classification mechanism and thus suppression of alerts, and
3338
also any security queries using taint tracking, as test classes act as
3439
default barriers stopping taint flow.
40+
* Parentheses are now no longer modelled directly in the AST, that is, the
41+
`ParExpr` class is empty. Instead, a parenthesized expression can be
42+
identified with the `Expr.isParenthesized()` member predicate.

change-notes/1.24/analysis-javascript.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
* Imports with the `.js` extension can now be resolved to a TypeScript file,
88
when the import refers to a file generated by TypeScript.
99

10-
- The analysis of sanitizer guards has improved, leading to fewer false-positive results from the security queries.
10+
* Imports that rely on path-mappings from a `tsconfig.json` file can now be resolved.
11+
12+
* The analysis of sanitizer guards has improved, leading to fewer false-positive results from the security queries.
1113

1214
* Support for the following frameworks and libraries has been improved:
1315
- [react](https://www.npmjs.com/package/react)
@@ -18,6 +20,7 @@
1820
- [Socket.IO](https://socket.io/)
1921
- [ws](https://github.com/websockets/ws)
2022
- [WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API)
23+
- [Koa](https://www.npmjs.com/package/koa)
2124

2225
## New queries
2326

@@ -39,6 +42,7 @@
3942
| Expression has no effect (`js/useless-expression`) | Fewer false positive results | The query now recognizes block-level flow type annotations and ignores the first statement of a try block. |
4043
| Use of call stack introspection in strict mode (`js/strict-mode-call-stack-introspection`) | Fewer false positive results | The query no longer flags expression statements. |
4144
| Missing CSRF middleware (`js/missing-token-validation`) | Fewer false positive results | The query reports fewer duplicates and only flags handlers that explicitly access cookie data. |
45+
| Uncontrolled data used in path expression (`js/path-injection`) | More results | This query now recognizes additional ways dangerous paths can be constructed. |
4246

4347
## Changes to libraries
4448

config/identical-files.json

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,9 +190,14 @@
190190
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstructionImports.qll",
191191
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstructionImports.qll"
192192
],
193-
"C++ SSA AliasAnalysis": [
193+
"SSA AliasAnalysis": [
194194
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll",
195-
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll"
195+
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll",
196+
"csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll"
197+
],
198+
"C++ SSA AliasAnalysisImports": [
199+
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysisImports.qll",
200+
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysisImports.qll"
196201
],
197202
"C++ IR ValueNumberingImports": [
198203
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingImports.qll",
@@ -203,6 +208,10 @@
203208
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll",
204209
"csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll"
205210
],
211+
"IR AliasConfiguration (unaliased_ssa)": [
212+
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasConfiguration.qll",
213+
"csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/AliasConfiguration.qll"
214+
],
206215
"IR SSA SSAConstruction": [
207216
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll",
208217
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll",

cpp/ql/src/semmle/code/cpp/commons/Printf.qll

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -258,14 +258,7 @@ class FormatLiteral extends Literal {
258258
* Gets the position in the string at which the nth conversion specifier
259259
* starts.
260260
*/
261-
int getConvSpecOffset(int n) {
262-
n = 0 and result = this.getFormat().indexOf("%", 0, 0)
263-
or
264-
n > 0 and
265-
exists(int p |
266-
n = p + 1 and result = this.getFormat().indexOf("%", 0, this.getConvSpecOffset(p) + 2)
267-
)
268-
}
261+
int getConvSpecOffset(int n) { result = this.getFormat().indexOf("%", n, 0) }
269262

270263
/*
271264
* Each of these predicates gets a regular expressions to match each individual

cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ private import cpp
66
private import semmle.code.cpp.dataflow.internal.FlowVar
77
private import semmle.code.cpp.models.interfaces.DataFlow
88
private import semmle.code.cpp.controlflow.Guards
9-
private import semmle.code.cpp.valuenumbering.GlobalValueNumbering
109

1110
cached
1211
private newtype TNode =
@@ -689,9 +688,9 @@ class BarrierGuard extends GuardCondition {
689688

690689
/** Gets a node guarded by this guard. */
691690
final ExprNode getAGuardedNode() {
692-
exists(GVN value, boolean branch |
693-
result.getExpr() = value.getAnExpr() and
694-
this.checks(value.getAnExpr(), branch) and
691+
exists(SsaDefinition def, Variable v, boolean branch |
692+
result.getExpr() = def.getAUse(v) and
693+
this.checks(def.getAUse(v), branch) and
695694
this.controls(result.getExpr().getBasicBlock(), branch)
696695
)
697696
}

cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll

Lines changed: 41 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -21,31 +21,19 @@ private predicate predictableInstruction(Instruction instr) {
2121
predictableInstruction(instr.(UnaryInstruction).getUnary())
2222
}
2323

24+
private DataFlow::Node getNodeForSource(Expr source) {
25+
isUserInput(source, _) and
26+
(
27+
result = DataFlow::exprNode(source)
28+
or
29+
result = DataFlow::definitionByReferenceNode(source)
30+
)
31+
}
32+
2433
private class DefaultTaintTrackingCfg extends DataFlow::Configuration {
2534
DefaultTaintTrackingCfg() { this = "DefaultTaintTrackingCfg" }
2635

27-
override predicate isSource(DataFlow::Node source) {
28-
exists(CallInstruction ci, WriteSideEffectInstruction wsei |
29-
userInputArgument(ci.getConvertedResultExpression(), wsei.getIndex()) and
30-
source.asInstruction() = wsei and
31-
wsei.getPrimaryInstruction() = ci
32-
)
33-
or
34-
userInputReturned(source.asExpr())
35-
or
36-
isUserInput(source.asExpr(), _)
37-
or
38-
source.asExpr() instanceof EnvironmentRead
39-
or
40-
source
41-
.asInstruction()
42-
.(LoadInstruction)
43-
.getSourceAddress()
44-
.(VariableAddressInstruction)
45-
.getASTVariable()
46-
.hasName("argv") and
47-
source.asInstruction().getEnclosingFunction().hasGlobalName("main")
48-
}
36+
override predicate isSource(DataFlow::Node source) { source = getNodeForSource(_) }
4937

5038
override predicate isSink(DataFlow::Node sink) { any() }
5139

@@ -59,7 +47,7 @@ private class DefaultTaintTrackingCfg extends DataFlow::Configuration {
5947
private class ToGlobalVarTaintTrackingCfg extends DataFlow::Configuration {
6048
ToGlobalVarTaintTrackingCfg() { this = "GlobalVarTaintTrackingCfg" }
6149

62-
override predicate isSource(DataFlow::Node source) { isUserInput(source.asExpr(), _) }
50+
override predicate isSource(DataFlow::Node source) { source = getNodeForSource(_) }
6351

6452
override predicate isSink(DataFlow::Node sink) {
6553
exists(GlobalOrNamespaceVariable gv | writesVariable(sink.asInstruction(), gv))
@@ -163,6 +151,22 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) {
163151
// from `a`.
164152
i2.(PointerAddInstruction).getLeft() = i1
165153
or
154+
// Until we have from through indirections across calls, we'll take flow out
155+
// of the parameter and into its indirection.
156+
exists(IRFunction f, Parameter parameter |
157+
i1 = getInitializeParameter(f, parameter) and
158+
i2 = getInitializeIndirection(f, parameter)
159+
)
160+
or
161+
// Until we have flow through indirections across calls, we'll take flow out
162+
// of the indirection and into the argument.
163+
// When we get proper flow through indirections across calls, this code can be
164+
// moved to `adjusedSink` or possibly into the `DataFlow::ExprNode` class.
165+
exists(ReadSideEffectInstruction read |
166+
read.getAnOperand().(SideEffectOperand).getAnyDef() = i1 and
167+
read.getArgumentDef() = i2
168+
)
169+
or
166170
// Flow from argument to return value
167171
i2 =
168172
any(CallInstruction call |
@@ -188,6 +192,18 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) {
188192
)
189193
}
190194

195+
pragma[noinline]
196+
private InitializeIndirectionInstruction getInitializeIndirection(IRFunction f, Parameter p) {
197+
result.getParameter() = p and
198+
result.getEnclosingIRFunction() = f
199+
}
200+
201+
pragma[noinline]
202+
private InitializeParameterInstruction getInitializeParameter(IRFunction f, Parameter p) {
203+
result.getParameter() = p and
204+
result.getEnclosingIRFunction() = f
205+
}
206+
191207
/**
192208
* Get an instruction that goes into argument `argumentIndex` of `call`. This
193209
* can be either directly or through one pointer indirection.
@@ -285,31 +301,11 @@ private Element adjustedSink(DataFlow::Node sink) {
285301
// For compatibility, send flow into a `NotExpr` even if it's part of a
286302
// short-circuiting condition and thus might get skipped.
287303
result.(NotExpr).getOperand() = sink.asExpr()
288-
or
289-
// For compatibility, send flow from argument read side effects to their
290-
// corresponding argument expression
291-
exists(IndirectReadSideEffectInstruction read |
292-
read.getAnOperand().(SideEffectOperand).getAnyDef() = sink.asInstruction() and
293-
read.getArgumentDef().getUnconvertedResultExpression() = result
294-
)
295-
or
296-
exists(BufferReadSideEffectInstruction read |
297-
read.getAnOperand().(SideEffectOperand).getAnyDef() = sink.asInstruction() and
298-
read.getArgumentDef().getUnconvertedResultExpression() = result
299-
)
300-
or
301-
exists(SizedBufferReadSideEffectInstruction read |
302-
read.getAnOperand().(SideEffectOperand).getAnyDef() = sink.asInstruction() and
303-
read.getArgumentDef().getUnconvertedResultExpression() = result
304-
)
305304
}
306305

307306
predicate tainted(Expr source, Element tainted) {
308307
exists(DefaultTaintTrackingCfg cfg, DataFlow::Node sink |
309-
cfg.hasFlow(DataFlow::exprNode(source), sink)
310-
or
311-
cfg.hasFlow(DataFlow::definitionByReferenceNode(source), sink)
312-
|
308+
cfg.hasFlow(getNodeForSource(source), sink) and
313309
tainted = adjustedSink(sink)
314310
)
315311
}
@@ -322,7 +318,7 @@ predicate taintedIncludingGlobalVars(Expr source, Element tainted, string global
322318
ToGlobalVarTaintTrackingCfg toCfg, FromGlobalVarTaintTrackingCfg fromCfg, DataFlow::Node store,
323319
GlobalOrNamespaceVariable global, DataFlow::Node load, DataFlow::Node sink
324320
|
325-
toCfg.hasFlow(DataFlow::exprNode(source), store) and
321+
toCfg.hasFlow(getNodeForSource(source), store) and
326322
store
327323
.asInstruction()
328324
.(StoreInstruction)

cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ private import cpp
66
private import semmle.code.cpp.ir.IR
77
private import semmle.code.cpp.controlflow.IRGuards
88
private import semmle.code.cpp.ir.ValueNumbering
9+
private import semmle.code.cpp.models.interfaces.DataFlow
910

1011
/**
1112
* A newtype wrapper to prevent accidental casts between `Node` and
@@ -289,6 +290,51 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction
289290
// Flow through the partial operand belongs in the taint-tracking libraries
290291
// for now.
291292
iTo.getAnOperand().(ChiTotalOperand).getDef() = iFrom
293+
or
294+
// Flow through modeled functions
295+
modelFlow(iFrom, iTo)
296+
}
297+
298+
private predicate modelFlow(Instruction iFrom, Instruction iTo) {
299+
exists(
300+
CallInstruction call, DataFlowFunction func, FunctionInput modelIn, FunctionOutput modelOut
301+
|
302+
call.getStaticCallTarget() = func and
303+
func.hasDataFlow(modelIn, modelOut)
304+
|
305+
(
306+
modelOut.isReturnValue() and
307+
iTo = call
308+
or
309+
// TODO: Add write side effects for return values
310+
modelOut.isReturnValueDeref() and
311+
iTo = call
312+
or
313+
exists(WriteSideEffectInstruction outNode |
314+
modelOut.isParameterDeref(outNode.getIndex()) and
315+
iTo = outNode and
316+
outNode.getPrimaryInstruction() = call
317+
)
318+
// TODO: add write side effects for qualifiers
319+
) and
320+
(
321+
exists(int index |
322+
modelIn.isParameter(index) and
323+
iFrom = call.getPositionalArgument(index)
324+
)
325+
or
326+
exists(int index, ReadSideEffectInstruction read |
327+
modelIn.isParameterDeref(index) and
328+
read.getIndex() = index and
329+
read.getPrimaryInstruction() = call and
330+
iFrom = read.getSideEffectOperand().getAnyDef()
331+
)
332+
or
333+
modelIn.isQualifierAddress() and
334+
iFrom = call.getThisArgument()
335+
// TODO: add read side effects for qualifiers
336+
)
337+
)
292338
}
293339

294340
/**

cpp/ql/src/semmle/code/cpp/ir/implementation/MemoryAccessKind.qll

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
private newtype TMemoryAccessKind =
22
TIndirectMemoryAccess() or
33
TBufferMemoryAccess() or
4+
TEntireAllocationMemoryAccess() or
45
TEscapedMemoryAccess() or
56
TNonLocalMemoryAccess() or
67
TPhiMemoryAccess() or
@@ -43,6 +44,16 @@ class BufferMemoryAccess extends MemoryAccessKind, TBufferMemoryAccess {
4344
final override predicate usesAddressOperand() { any() }
4445
}
4546

47+
/**
48+
* The operand or results accesses all memory in the contiguous allocation that contains the address
49+
* specified by the `AddressOperand` on the same instruction.
50+
*/
51+
class EntireAllocationMemoryAccess extends MemoryAccessKind, TEntireAllocationMemoryAccess {
52+
override string toString() { result = "alloc" }
53+
54+
final override predicate usesAddressOperand() { any() }
55+
}
56+
4657
/**
4758
* The operand or result accesses all memory whose address has escaped.
4859
*/

0 commit comments

Comments
 (0)