Skip to content

Commit 476f27e

Browse files
author
Dave Bartolomeo
committed
Merge from master
2 parents 01ef879 + 0d8472b commit 476f27e

File tree

57 files changed

+3540
-1525
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

+3540
-1525
lines changed

.devcontainer/devcontainer.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"extensions": [
3+
"github.vscode-codeql",
4+
"slevesque.vscode-zipexplorer"
5+
],
6+
"settings": {
7+
"codeQL.experimentalBqrsParsing": true
8+
}
9+
}

cpp/ql/src/semmle/code/cpp/controlflow/BasicBlocks.qll

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
/**
2+
* Provides a library for reasoning about control flow at the granularity of basic blocks.
3+
* This is usually much more efficient than reasoning directly at the level of `ControlFlowNode`s.
4+
*/
5+
16
import cpp
27
private import internal.PrimitiveBasicBlocks
38
private import internal.ConstantExprs
@@ -148,22 +153,37 @@ predicate bb_successor = bb_successor_cached/2;
148153
class BasicBlock extends ControlFlowNodeBase {
149154
BasicBlock() { basic_block_entry_node(this) }
150155

156+
/** Holds if this basic block contains `node`. */
151157
predicate contains(ControlFlowNode node) { basic_block_member(node, this, _) }
152158

159+
/** Gets the `ControlFlowNode` at position `pos` in this basic block. */
153160
ControlFlowNode getNode(int pos) { basic_block_member(result, this, pos) }
154161

162+
/** Gets a `ControlFlowNode` in this basic block. */
155163
ControlFlowNode getANode() { basic_block_member(result, this, _) }
156164

165+
/** Gets a `BasicBlock` that is a direct successor of this basic block. */
157166
BasicBlock getASuccessor() { bb_successor(this, result) }
158167

168+
/** Gets a `BasicBlock` that is a direct predecessor of this basic block. */
159169
BasicBlock getAPredecessor() { bb_successor(result, this) }
160170

171+
/**
172+
* Gets a `BasicBlock` such that the control-flow edge `(this, result)` may be taken
173+
* when the outgoing edge of this basic block is an expression that is true.
174+
*/
161175
BasicBlock getATrueSuccessor() { result.getStart() = this.getEnd().getATrueSuccessor() }
162176

177+
/**
178+
* Gets a `BasicBlock` such that the control-flow edge `(this, result)` may be taken
179+
* when the outgoing edge of this basic block is an expression that is false.
180+
*/
163181
BasicBlock getAFalseSuccessor() { result.getStart() = this.getEnd().getAFalseSuccessor() }
164182

183+
/** Gets the final `ControlFlowNode` of this basic block. */
165184
ControlFlowNode getEnd() { basic_block_member(result, this, bb_length(this) - 1) }
166185

186+
/** Gets the first `ControlFlowNode` of this basic block. */
167187
ControlFlowNode getStart() { result = this }
168188

169189
/** Gets the number of `ControlFlowNode`s in this basic block. */
@@ -192,6 +212,7 @@ class BasicBlock extends ControlFlowNodeBase {
192212
this.getEnd().getLocation().hasLocationInfo(endf, _, _, endl, endc)
193213
}
194214

215+
/** Gets the function containing this basic block. */
195216
Function getEnclosingFunction() { result = this.getStart().getControlFlowScope() }
196217

197218
/**

cpp/ql/src/semmle/code/cpp/controlflow/ControlFlowGraph.qll

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
/**
2+
* Provides a library for reasoning about control flow at the granularity of
3+
* individual nodes in the control-flow graph.
4+
*/
5+
16
import cpp
27
import BasicBlocks
38
private import semmle.code.cpp.controlflow.internal.ConstantExprs
@@ -29,8 +34,10 @@ private import semmle.code.cpp.controlflow.internal.CFG
2934
* `Handler`. There are no edges from function calls to `Handler`s.
3035
*/
3136
class ControlFlowNode extends Locatable, ControlFlowNodeBase {
37+
/** Gets a direct successor of this control-flow node, if any. */
3238
ControlFlowNode getASuccessor() { successors_adapted(this, result) }
3339

40+
/** Gets a direct predecessor of this control-flow node, if any. */
3441
ControlFlowNode getAPredecessor() { this = result.getASuccessor() }
3542

3643
/** Gets the function containing this control-flow node. */
@@ -71,6 +78,7 @@ class ControlFlowNode extends Locatable, ControlFlowNodeBase {
7178
result = getASuccessor()
7279
}
7380

81+
/** Gets the `BasicBlock` containing this control-flow node. */
7482
BasicBlock getBasicBlock() { result.getANode() = this }
7583
}
7684

@@ -86,10 +94,18 @@ import ControlFlowGraphPublic
8694
*/
8795
class ControlFlowNodeBase extends ElementBase, @cfgnode { }
8896

97+
/**
98+
* Holds when `n2` is a control-flow node such that the control-flow
99+
* edge `(n1, n2)` may be taken when `n1` is an expression that is true.
100+
*/
89101
predicate truecond_base(ControlFlowNodeBase n1, ControlFlowNodeBase n2) {
90102
qlCFGTrueSuccessor(n1, n2)
91103
}
92104

105+
/**
106+
* Holds when `n2` is a control-flow node such that the control-flow
107+
* edge `(n1, n2)` may be taken when `n1` is an expression that is false.
108+
*/
93109
predicate falsecond_base(ControlFlowNodeBase n1, ControlFlowNodeBase n2) {
94110
qlCFGFalseSuccessor(n1, n2)
95111
}

cpp/ql/src/semmle/code/cpp/controlflow/Dataflow.qll

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,25 @@ import Dereferenced
1515
abstract class DataflowAnnotation extends string {
1616
DataflowAnnotation() { this = "pointer-null" or this = "pointer-valid" }
1717

18+
/** Holds if this annotation is the default annotation. */
1819
abstract predicate isDefault();
1920

21+
/** Holds if this annotation is generated when analyzing expression `e`. */
2022
abstract predicate generatedOn(Expr e);
2123

24+
/**
25+
* Holds if this annotation is generated for the variable `v` when
26+
* the control-flow edge `(src, dest)` is taken.
27+
*/
2228
abstract predicate generatedBy(LocalScopeVariable v, ControlFlowNode src, ControlFlowNode dest);
2329

30+
/**
31+
* Holds if this annotation is removed for the variable `v` when
32+
* the control-flow edge `(src, dest)` is taken.
33+
*/
2434
abstract predicate killedBy(LocalScopeVariable v, ControlFlowNode src, ControlFlowNode dest);
2535

36+
/** Holds if expression `e` is given this annotation. */
2637
predicate marks(Expr e) {
2738
this.generatedOn(e) and reachable(e)
2839
or
@@ -31,6 +42,7 @@ abstract class DataflowAnnotation extends string {
3142
exists(LocalScopeVariable v | this.marks(v, e) and e = v.getAnAccess())
3243
}
3344

45+
/** Holds if the variable `v` accessed in control-flow node `n` is given this annotation. */
3446
predicate marks(LocalScopeVariable v, ControlFlowNode n) {
3547
v.getAnAccess().getEnclosingFunction().getBlock() = n and
3648
this.isDefault()
@@ -57,13 +69,21 @@ abstract class DataflowAnnotation extends string {
5769
)
5870
}
5971

72+
/**
73+
* Holds if the variable `v` preserves this annotation when the control-flow
74+
* edge `(src, dest)` is taken.
75+
*/
6076
predicate preservedBy(LocalScopeVariable v, ControlFlowNode src, ControlFlowNode dest) {
6177
this.marks(v, src) and
6278
src.getASuccessor() = dest and
6379
not v.getInitializer() = dest and
6480
not v.getAnAssignment() = src
6581
}
6682

83+
/**
84+
* Holds if the variable `v` is assigned this annotation when `src` is an assignment
85+
* expression that assigns to `v` and the control-flow edge `(src, dest)` is taken.
86+
*/
6787
predicate assignedBy(LocalScopeVariable v, ControlFlowNode src, ControlFlowNode dest) {
6888
this.marks(src.(AssignExpr).getRValue()) and
6989
src = v.getAnAssignment() and

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import cpp
22
import semmle.code.cpp.security.Security
33
private import semmle.code.cpp.ir.dataflow.DataFlow
4+
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
45
private import semmle.code.cpp.ir.dataflow.DataFlow2
56
private import semmle.code.cpp.ir.dataflow.DataFlow3
67
private import semmle.code.cpp.ir.IR

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

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,7 @@ class Node extends TIRDataFlowNode {
7171
* `x.set(taint())` is a partial definition of `x`, and `transfer(&x, taint())` is
7272
* a partial definition of `&x`).
7373
*/
74-
Expr asPartialDefinition() {
75-
result = this.(PartialDefinitionNode).getInstruction().getUnconvertedResultExpression()
76-
}
74+
Expr asPartialDefinition() { result = this.(PartialDefinitionNode).getDefinedExpr() }
7775

7876
/**
7977
* DEPRECATED: See UninitializedNode.
@@ -162,11 +160,7 @@ class ExprNode extends InstructionNode {
162160
* as `x` in `f(x)` and implicit parameters such as `this` in `x.f()`
163161
*/
164162
class ParameterNode extends InstructionNode {
165-
ParameterNode() {
166-
instr instanceof InitializeParameterInstruction
167-
or
168-
instr instanceof InitializeThisInstruction
169-
}
163+
override InitializeParameterInstruction instr;
170164

171165
/**
172166
* Holds if this node is the parameter of `c` at the specified (zero-based)
@@ -180,7 +174,7 @@ class ParameterNode extends InstructionNode {
180174
* flow graph.
181175
*/
182176
private class ExplicitParameterNode extends ParameterNode {
183-
override InitializeParameterInstruction instr;
177+
ExplicitParameterNode() { exists(instr.getParameter()) }
184178

185179
override predicate isParameterOf(Function f, int i) { f.getParameter(i) = instr.getParameter() }
186180

@@ -191,7 +185,7 @@ private class ExplicitParameterNode extends ParameterNode {
191185
}
192186

193187
private class ThisParameterNode extends ParameterNode {
194-
override InitializeThisInstruction instr;
188+
ThisParameterNode() { instr.getIRVariable() instanceof IRThisVariable }
195189

196190
override predicate isParameterOf(Function f, int i) {
197191
i = -1 and instr.getEnclosingFunction() = f
@@ -251,14 +245,17 @@ abstract class PostUpdateNode extends InstructionNode {
251245
* setY(&x); // a partial definition of the object `x`.
252246
* ```
253247
*/
254-
abstract private class PartialDefinitionNode extends PostUpdateNode, TInstructionNode { }
248+
abstract private class PartialDefinitionNode extends PostUpdateNode, TInstructionNode {
249+
abstract Expr getDefinedExpr();
250+
}
255251

256252
private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
257253
override ChiInstruction instr;
254+
FieldAddressInstruction field;
258255

259256
ExplicitFieldStoreQualifierNode() {
260257
not instr.isResultConflated() and
261-
exists(StoreInstruction store, FieldInstruction field |
258+
exists(StoreInstruction store |
262259
instr.getPartial() = store and field = store.getDestinationAddress()
263260
)
264261
}
@@ -268,6 +265,10 @@ private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
268265
// DataFlowImplConsistency::Consistency. However, it's not clear what (if any) implications
269266
// this consistency failure has.
270267
override Node getPreUpdateNode() { result.asInstruction() = instr.getTotal() }
268+
269+
override Expr getDefinedExpr() {
270+
result = field.getObjectAddress().getUnconvertedResultExpression()
271+
}
271272
}
272273

273274
/**
@@ -278,15 +279,18 @@ private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
278279
*/
279280
private class ExplicitSingleFieldStoreQualifierNode extends PartialDefinitionNode {
280281
override StoreInstruction instr;
282+
FieldAddressInstruction field;
281283

282284
ExplicitSingleFieldStoreQualifierNode() {
283-
exists(FieldAddressInstruction field |
284-
field = instr.getDestinationAddress() and
285-
not exists(ChiInstruction chi | chi.getPartial() = instr)
286-
)
285+
field = instr.getDestinationAddress() and
286+
not exists(ChiInstruction chi | chi.getPartial() = instr)
287287
}
288288

289289
override Node getPreUpdateNode() { none() }
290+
291+
override Expr getDefinedExpr() {
292+
result = field.getObjectAddress().getUnconvertedResultExpression()
293+
}
290294
}
291295

292296
/**
@@ -458,9 +462,9 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction
458462
// for now.
459463
iTo.getAnOperand().(ChiTotalOperand).getDef() = iFrom
460464
or
461-
// The next two rules allow flow from partial definitions in setters to succeeding loads in the caller.
462-
// First, we add flow from write side-effects to non-conflated chi instructions through their
463-
// partial operands. Consider the following example:
465+
// Add flow from write side-effects to non-conflated chi instructions through their
466+
// partial operands. From there, a `readStep` will find subsequent reads of that field.
467+
// Consider the following example:
464468
// ```
465469
// void setX(Point* p, int new_x) {
466470
// p->x = new_x;
@@ -470,14 +474,9 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction
470474
// ```
471475
// Here, a `WriteSideEffectInstruction` will provide a new definition for `p->x` after the call to
472476
// `setX`, which will be melded into `p` through a chi instruction.
473-
iTo.getAnOperand().(ChiPartialOperand).getDef() = iFrom.(WriteSideEffectInstruction) and
474-
not iTo.isResultConflated()
475-
or
476-
// Next, we add flow from non-conflated chi instructions to loads (even when they are not precise).
477-
// This ensures that loads of `p->x` gets data flow from the `WriteSideEffectInstruction` above.
478-
exists(ChiInstruction chi | iFrom = chi |
479-
not chi.isResultConflated() and
480-
iTo.(LoadInstruction).getSourceValueOperand().getAnyDef() = chi
477+
exists(ChiInstruction chi | chi = iTo |
478+
chi.getPartialOperand().getDef() = iFrom.(WriteSideEffectInstruction) and
479+
not chi.isResultConflated()
481480
)
482481
or
483482
// Flow from stores to structs with a single field to a load of that field.

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,15 @@ class IREllipsisVariable extends IRTempVariable {
223223
final override string toString() { result = "#ellipsis" }
224224
}
225225

226+
/**
227+
* A temporary variable generated to hold the `this` pointer.
228+
*/
229+
class IRThisVariable extends IRTempVariable {
230+
IRThisVariable() { tag = ThisTempVar() }
231+
232+
final override string toString() { result = "#this" }
233+
}
234+
226235
/**
227236
* A variable generated to represent the contents of a string literal. This variable acts much like
228237
* a read-only global variable.

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ private predicate isArgumentForParameter(CallInstruction ci, Operand operand, In
204204
init.(InitializeParameterInstruction).getParameter() =
205205
f.getParameter(operand.(PositionalArgumentOperand).getIndex())
206206
or
207-
init instanceof InitializeThisInstruction and
207+
init.(InitializeParameterInstruction).getIRVariable() instanceof IRThisVariable and
208208
init.getEnclosingFunction() = f and
209209
operand instanceof ThisArgumentOperand
210210
) and

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasConfiguration.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ private import AliasAnalysis
55

66
private newtype TAllocation =
77
TVariableAllocation(IRVariable var) or
8-
TIndirectParameterAllocation(IRAutomaticUserVariable var) {
8+
TIndirectParameterAllocation(IRAutomaticVariable var) {
99
exists(InitializeIndirectionInstruction instr | instr.getIRVariable() = var)
1010
} or
1111
TDynamicAllocation(CallInstruction call) {
@@ -74,7 +74,7 @@ class VariableAllocation extends Allocation, TVariableAllocation {
7474
}
7575

7676
class IndirectParameterAllocation extends Allocation, TIndirectParameterAllocation {
77-
IRAutomaticUserVariable var;
77+
IRAutomaticVariable var;
7878

7979
IndirectParameterAllocation() { this = TIndirectParameterAllocation(var) }
8080

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRVariable.qll

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,15 @@ class IREllipsisVariable extends IRTempVariable {
223223
final override string toString() { result = "#ellipsis" }
224224
}
225225

226+
/**
227+
* A temporary variable generated to hold the `this` pointer.
228+
*/
229+
class IRThisVariable extends IRTempVariable {
230+
IRThisVariable() { tag = ThisTempVar() }
231+
232+
final override string toString() { result = "#this" }
233+
}
234+
226235
/**
227236
* A variable generated to represent the contents of a string literal. This variable acts much like
228237
* a read-only global variable.

0 commit comments

Comments
 (0)