Skip to content

Commit 8b254f7

Browse files
committed
Merge remote-tracking branch 'upstream/master' into Maps
2 parents 69a16af + e965e5c commit 8b254f7

File tree

57 files changed

+2609
-11599
lines changed

Some content is hidden

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

57 files changed

+2609
-11599
lines changed

change-notes/1.24/analysis-cpp.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ The following changes in version 1.24 affect C/C++ analysis in all applications.
2525
| Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) | | This query is no longer run on LGTM. |
2626
| No space for zero terminator (`cpp/no-space-for-terminator`) | Fewer false positive results | This query has been modified to be more conservative when identifying which pointers point to null-terminated strings. This approach produces fewer, more accurate results. |
2727
| Overflow in uncontrolled allocation size (`cpp/uncontrolled-allocation-size`) | Fewer false positive results | Cases where the tainted allocation size is range checked are now more reliably excluded. |
28+
| Overflow in uncontrolled allocation size (`cpp/uncontrolled-allocation-size`) | Fewer false positive results | The query now produces fewer, more accurate results. |
2829
| Overloaded assignment does not return 'this' (`cpp/assignment-does-not-return-this`) | Fewer false positive results | This query no longer reports incorrect results in template classes. |
2930
| Unsafe array for days of the year (`cpp/leap-year/unsafe-array-for-days-of-the-year`) | | This query is no longer run on LGTM. |
3031
| Unsigned comparison to zero (`cpp/unsigned-comparison-zero`) | More correct results | This query now also looks for comparisons of the form `0 <= x`. |

change-notes/1.24/analysis-javascript.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@
8686
| Useless regular-expression character escape (`js/useless-regexp-character-escape`) | Fewer false positive results | This query now distinguishes escapes in strings and regular expression literals. |
8787
| Identical operands (`js/redundant-operation`) | Fewer results | This query now recognizes cases where the operands change a value using ++/-- expressions. |
8888
| Superfluous trailing arguments (`js/superfluous-trailing-arguments`) | Fewer results | This query now recognizes cases where a function uses the `Function.arguments` value to process a variable number of parameters. |
89-
| Incomplete URL scheme check (`js/incomplete-url-scheme-check`) | More results | This query now recognizes more variations of URL scheme checks. |
89+
| Incomplete URL scheme check (`js/incomplete-url-scheme-check`) | More results | This query now recognizes additional variations of URL scheme checks. |
9090

9191
## Changes to libraries
9292

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Improvements to JavaScript analysis
2+
3+
## General improvements
4+
5+
6+
## New queries
7+
8+
| **Query** | **Tags** | **Purpose** |
9+
|---------------------------------------------------------------------------------|-------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
10+
11+
12+
## Changes to existing queries
13+
14+
| **Query** | **Expected impact** | **Change** |
15+
|--------------------------------|------------------------------|---------------------------------------------------------------------------|
16+
| Misspelled variable name (`js/misspelled-variable-name`) | Message changed | The message for this query now correctly identifies the misspelled variable in additional cases. |
17+
| Uncontrolled data used in path expression (`js/path-injection`) | More results | This query now recognizes additional file system calls. |
18+
| Uncontrolled command line (`js/command-line-injection`) | More results | This query now recognizes additional command execution calls. |
19+
20+
## Changes to libraries
21+
22+

cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,31 +15,31 @@ import cpp
1515
import semmle.code.cpp.security.TaintTracking
1616
import TaintedWithPath
1717

18-
predicate taintedChild(Expr e, Expr tainted) {
19-
(
20-
isAllocationExpr(e)
21-
or
22-
any(MulExpr me | me.getAChild() instanceof SizeofOperator) = e
23-
) and
24-
tainted = e.getAChild() and
18+
/**
19+
* Holds if `alloc` is an allocation, and `tainted` is a child of it that is a
20+
* taint sink.
21+
*/
22+
predicate allocSink(Expr alloc, Expr tainted) {
23+
isAllocationExpr(alloc) and
24+
tainted = alloc.getAChild() and
2525
tainted.getUnspecifiedType() instanceof IntegralType
2626
}
2727

2828
class TaintedAllocationSizeConfiguration extends TaintTrackingConfiguration {
29-
override predicate isSink(Element tainted) { taintedChild(_, tainted) }
29+
override predicate isSink(Element tainted) { allocSink(_, tainted) }
3030
}
3131

3232
predicate taintedAllocSize(
33-
Expr e, Expr source, PathNode sourceNode, PathNode sinkNode, string taintCause
33+
Expr source, Expr alloc, PathNode sourceNode, PathNode sinkNode, string taintCause
3434
) {
3535
isUserInput(source, taintCause) and
3636
exists(Expr tainted |
37-
taintedChild(e, tainted) and
37+
allocSink(alloc, tainted) and
3838
taintedWithPath(source, tainted, sourceNode, sinkNode)
3939
)
4040
}
4141

42-
from Expr e, Expr source, PathNode sourceNode, PathNode sinkNode, string taintCause
43-
where taintedAllocSize(e, source, sourceNode, sinkNode, taintCause)
44-
select e, sourceNode, sinkNode, "This allocation size is derived from $@ and might overflow",
42+
from Expr source, Expr alloc, PathNode sourceNode, PathNode sinkNode, string taintCause
43+
where taintedAllocSize(source, alloc, sourceNode, sinkNode, taintCause)
44+
select alloc, sourceNode, sinkNode, "This allocation size is derived from $@ and might overflow",
4545
source, "user input (" + taintCause + ")"

cpp/ql/src/semmle/code/cpp/Class.qll

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,15 @@ class Class extends UserType {
458458
exists(ClassDerivation d | d.getDerivedClass() = this and d = result)
459459
}
460460

461+
/**
462+
* Gets class derivation number `index` of this class/struct, for example the
463+
* `public B` is derivation 1 in the following code:
464+
* ```
465+
* class D : public A, public B, public C {
466+
* ...
467+
* };
468+
* ```
469+
*/
461470
ClassDerivation getDerivation(int index) {
462471
exists(ClassDerivation d | d.getDerivedClass() = this and d.getIndex() = index and d = result)
463472
}
@@ -900,6 +909,22 @@ class AbstractClass extends Class {
900909
class TemplateClass extends Class {
901910
TemplateClass() { usertypes(underlyingElement(this), _, 6) }
902911

912+
/**
913+
* Gets a class instantiated from this template.
914+
*
915+
* For example for `MyTemplateClass<T>` in the following code, the results are
916+
* `MyTemplateClass<int>` and `MyTemplateClass<long>`:
917+
* ```
918+
* template<class T>
919+
* class MyTemplateClass {
920+
* ...
921+
* };
922+
*
923+
* MyTemplateClass<int> instance;
924+
*
925+
* MyTemplateClass<long> instance;
926+
* ```
927+
*/
903928
Class getAnInstantiation() {
904929
result.isConstructedFrom(this) and
905930
exists(result.getATemplateArgument())

cpp/ql/src/semmle/code/cpp/Comments.qll

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,20 @@ class Comment extends Locatable, @comment {
1313

1414
override Location getLocation() { comments(underlyingElement(this), _, result) }
1515

16+
/**
17+
* Gets the text of this comment, including the opening `//` or `/*`, and the closing `*``/` if
18+
* present.
19+
*/
1620
string getContents() { comments(underlyingElement(this), result, _) }
1721

22+
/**
23+
* Gets the AST element this comment is associated with. For example, the comment in the
24+
* following code is associated with the declaration of `j`.
25+
* ```
26+
* int i;
27+
* int j; // Comment on j
28+
* ```
29+
*/
1830
Element getCommentedElement() {
1931
commentbinding(underlyingElement(this), unresolveElement(result))
2032
}

cpp/ql/src/semmle/code/cpp/Compilation.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class Compilation extends @compilation {
4040
/** Gets a file compiled during this invocation. */
4141
File getAFileCompiled() { result = getFileCompiled(_) }
4242

43+
/** Gets the `i`th file compiled during this invocation */
4344
File getFileCompiled(int i) { compilation_compiling_files(this, i, unresolveElement(result)) }
4445

4546
/**

cpp/ql/src/semmle/code/cpp/Diagnostics.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ class Diagnostic extends Locatable, @diagnostic {
1111
/** Gets the error code for this compiler message. */
1212
string getTag() { diagnostics(underlyingElement(this), _, result, _, _, _) }
1313

14+
/** Holds if `s` is the error code for this compiler message. */
1415
predicate hasTag(string s) { this.getTag() = s }
1516

1617
/**

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

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,12 @@ private class ArrayContent extends Content, TArrayContent {
186186
* value of `node1`.
187187
*/
188188
predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
189-
none() // stub implementation
189+
exists(FieldAddressInstruction fa, StoreInstruction store |
190+
node1.asInstruction() = store and
191+
store.getDestinationAddress() = fa and
192+
node2.asInstruction().(ChiInstruction).getPartial() = store and
193+
f.(FieldContent).getField() = fa.getField()
194+
)
190195
}
191196

192197
/**
@@ -195,7 +200,12 @@ predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
195200
* `node2`.
196201
*/
197202
predicate readStep(Node node1, Content f, Node node2) {
198-
none() // stub implementation
203+
exists(FieldAddressInstruction fa, LoadInstruction load |
204+
load.getSourceAddress() = fa and
205+
node1.asInstruction() = load.getSourceValueOperand().getAnyDef() and
206+
fa.getField() = f.(FieldContent).getField() and
207+
load = node2.asInstruction()
208+
)
199209
}
200210

201211
/**

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

Lines changed: 99 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,26 @@ class Node extends TIRDataFlowNode {
5555
Expr asDefiningArgument() { result = this.(DefinitionByReferenceNode).getArgument() }
5656

5757
/** Gets the parameter corresponding to this node, if any. */
58-
Parameter asParameter() { result = this.(ParameterNode).getParameter() }
58+
Parameter asParameter() { result = this.(ExplicitParameterNode).getParameter() }
5959

6060
/**
6161
* Gets the variable corresponding to this node, if any. This can be used for
6262
* modelling flow in and out of global variables.
6363
*/
6464
Variable asVariable() { result = this.(VariableNode).getVariable() }
6565

66+
/**
67+
* Gets the expression that is partially defined by this node, if any.
68+
*
69+
* Partial definitions are created for field stores (`x.y = taint();` is a partial
70+
* definition of `x`), and for calls that may change the value of an object (so
71+
* `x.set(taint())` is a partial definition of `x`, and `transfer(&x, taint())` is
72+
* a partial definition of `&x`).
73+
*/
74+
Expr asPartialDefinition() {
75+
result = this.(PartialDefinitionNode).getInstruction().getUnconvertedResultExpression()
76+
}
77+
6678
/**
6779
* DEPRECATED: See UninitializedNode.
6880
*
@@ -96,6 +108,9 @@ class Node extends TIRDataFlowNode {
96108
string toString() { none() } // overridden by subclasses
97109
}
98110

111+
/**
112+
* An instruction, viewed as a node in a data flow graph.
113+
*/
99114
class InstructionNode extends Node, TInstructionNode {
100115
Instruction instr;
101116

@@ -143,26 +158,45 @@ class ExprNode extends InstructionNode {
143158
}
144159

145160
/**
146-
* The value of a parameter at function entry, viewed as a node in a data
147-
* flow graph.
161+
* A node representing a `Parameter`. This includes both explicit parameters such
162+
* as `x` in `f(x)` and implicit parameters such as `this` in `x.f()`
148163
*/
149164
class ParameterNode extends InstructionNode {
150-
override InitializeParameterInstruction instr;
165+
ParameterNode() {
166+
instr instanceof InitializeParameterInstruction
167+
or
168+
instr instanceof InitializeThisInstruction
169+
}
151170

152171
/**
153172
* Holds if this node is the parameter of `c` at the specified (zero-based)
154173
* position. The implicit `this` parameter is considered to have index `-1`.
155174
*/
156-
predicate isParameterOf(Function f, int i) { f.getParameter(i) = instr.getParameter() }
175+
predicate isParameterOf(Function f, int i) { none() } // overriden by subclasses
176+
}
177+
178+
/**
179+
* The value of a parameter at function entry, viewed as a node in a data
180+
* flow graph.
181+
*/
182+
private class ExplicitParameterNode extends ParameterNode {
183+
override InitializeParameterInstruction instr;
157184

185+
override predicate isParameterOf(Function f, int i) { f.getParameter(i) = instr.getParameter() }
186+
187+
/** Gets the parameter corresponding to this node. */
158188
Parameter getParameter() { result = instr.getParameter() }
159189

160190
override string toString() { result = instr.getParameter().toString() }
161191
}
162192

163-
private class ThisParameterNode extends InstructionNode {
193+
private class ThisParameterNode extends ParameterNode {
164194
override InitializeThisInstruction instr;
165195

196+
override predicate isParameterOf(Function f, int i) {
197+
i = -1 and instr.getEnclosingFunction() = f
198+
}
199+
166200
override string toString() { result = "this" }
167201
}
168202

@@ -204,6 +238,38 @@ abstract class PostUpdateNode extends InstructionNode {
204238
abstract Node getPreUpdateNode();
205239
}
206240

241+
/**
242+
* The base class for nodes that perform "partial definitions".
243+
*
244+
* In contrast to a normal "definition", which provides a new value for
245+
* something, a partial definition is an expression that may affect a
246+
* value, but does not necessarily replace it entirely. For example:
247+
* ```
248+
* x.y = 1; // a partial definition of the object `x`.
249+
* x.y.z = 1; // a partial definition of the object `x.y`.
250+
* x.setY(1); // a partial definition of the object `x`.
251+
* setY(&x); // a partial definition of the object `x`.
252+
* ```
253+
*/
254+
abstract private class PartialDefinitionNode extends PostUpdateNode, TInstructionNode { }
255+
256+
private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
257+
override ChiInstruction instr;
258+
259+
ExplicitFieldStoreQualifierNode() {
260+
not instr.isResultConflated() and
261+
exists(StoreInstruction store, FieldInstruction field |
262+
instr.getPartial() = store and field = store.getDestinationAddress()
263+
)
264+
}
265+
266+
// There might be multiple `ChiInstructions` that has a particular instruction as
267+
// the total operand - so this definition gives consistency errors in
268+
// DataFlowImplConsistency::Consistency. However, it's not clear what (if any) implications
269+
// this consistency failure has.
270+
override Node getPreUpdateNode() { result.asInstruction() = instr.getTotal() }
271+
}
272+
207273
/**
208274
* A node that represents the value of a variable after a function call that
209275
* may have changed the variable because it's passed by reference.
@@ -288,6 +354,10 @@ class VariableNode extends Node, TVariableNode {
288354
*/
289355
InstructionNode instructionNode(Instruction instr) { result.getInstruction() = instr }
290356

357+
/**
358+
* Gets the `Node` corresponding to a definition by reference of the variable
359+
* that is passed as `argument` of a call.
360+
*/
291361
DefinitionByReferenceNode definitionByReferenceNode(Expr e) { result.getArgument() = e }
292362

293363
/**
@@ -305,7 +375,7 @@ ExprNode convertedExprNode(Expr e) { result.getConvertedExpr() = e }
305375
/**
306376
* Gets the `Node` corresponding to the value of `p` at function entry.
307377
*/
308-
ParameterNode parameterNode(Parameter p) { result.getParameter() = p }
378+
ExplicitParameterNode parameterNode(Parameter p) { result.getParameter() = p }
309379

310380
/** Gets the `VariableNode` corresponding to the variable `v`. */
311381
VariableNode variableNode(Variable v) { result.getVariable() = v }
@@ -360,6 +430,28 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction
360430
// for now.
361431
iTo.getAnOperand().(ChiTotalOperand).getDef() = iFrom
362432
or
433+
// The next two rules allow flow from partial definitions in setters to succeeding loads in the caller.
434+
// First, we add flow from write side-effects to non-conflated chi instructions through their
435+
// partial operands. Consider the following example:
436+
// ```
437+
// void setX(Point* p, int new_x) {
438+
// p->x = new_x;
439+
// }
440+
// ...
441+
// setX(&p, taint());
442+
// ```
443+
// Here, a `WriteSideEffectInstruction` will provide a new definition for `p->x` after the call to
444+
// `setX`, which will be melded into `p` through a chi instruction.
445+
iTo.getAnOperand().(ChiPartialOperand).getDef() = iFrom.(WriteSideEffectInstruction) and
446+
not iTo.isResultConflated()
447+
or
448+
// Next, we add flow from non-conflated chi instructions to loads (even when they are not precise).
449+
// This ensures that loads of `p->x` gets data flow from the `WriteSideEffectInstruction` above.
450+
exists(ChiInstruction chi | iFrom = chi |
451+
not chi.isResultConflated() and
452+
iTo.(LoadInstruction).getSourceValueOperand().getAnyDef() = chi
453+
)
454+
or
363455
// Flow through modeled functions
364456
modelFlow(iFrom, iTo)
365457
}

0 commit comments

Comments
 (0)