Skip to content

Commit 4317381

Browse files
authored
Merge pull request #11171 from MathiasVP/global-flow
2 parents ce8a84a + ae774a6 commit 4317381

17 files changed

Lines changed: 414 additions & 100 deletions

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

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -500,21 +500,25 @@ OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) {
500500
*/
501501
predicate jumpStep(Node n1, Node n2) {
502502
exists(Cpp::GlobalOrNamespaceVariable v |
503-
v =
504-
n1.asInstruction()
505-
.(StoreInstruction)
506-
.getResultAddress()
507-
.(VariableAddressInstruction)
508-
.getAstVariable() and
509-
v = n2.asVariable()
503+
exists(Ssa::GlobalUse globalUse |
504+
v = globalUse.getVariable() and
505+
n1.(FinalGlobalValue).getGlobalUse() = globalUse
506+
|
507+
globalUse.getIndirectionIndex() = 1 and
508+
v = n2.asVariable()
509+
or
510+
v = n2.asIndirectVariable(globalUse.getIndirectionIndex())
511+
)
510512
or
511-
v =
512-
n2.asInstruction()
513-
.(LoadInstruction)
514-
.getSourceAddress()
515-
.(VariableAddressInstruction)
516-
.getAstVariable() and
517-
v = n1.asVariable()
513+
exists(Ssa::GlobalDef globalDef |
514+
v = globalDef.getVariable() and
515+
n2.(InitialGlobalValue).getGlobalDef() = globalDef
516+
|
517+
globalDef.getIndirectionIndex() = 1 and
518+
v = n1.asVariable()
519+
or
520+
v = n1.asIndirectVariable(globalDef.getIndirectionIndex())
521+
)
518522
)
519523
}
520524

@@ -696,6 +700,10 @@ predicate nodeIsHidden(Node n) {
696700
n instanceof OperandNode and
697701
not n instanceof ArgumentNode and
698702
not n.asOperand() instanceof StoreValueOperand
703+
or
704+
n instanceof FinalGlobalValue
705+
or
706+
n instanceof InitialGlobalValue
699707
}
700708

701709
class LambdaCallKind = Unit;

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

Lines changed: 103 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ private import DataFlowImplCommon as DataFlowImplCommon
3232
cached
3333
private newtype TIRDataFlowNode =
3434
TNode0(Node0Impl node) { DataFlowImplCommon::forceCachingInSameStage() } or
35-
TVariableNode(Variable var) or
35+
TVariableNode(Variable var, int indirectionIndex) {
36+
indirectionIndex = [1 .. Ssa::getMaxIndirectionsForType(var.getUnspecifiedType())]
37+
} or
3638
TPostFieldUpdateNode(FieldAddress operand, int indirectionIndex) {
3739
indirectionIndex =
3840
[1 .. Ssa::countIndirectionsForCppType(operand.getObjectAddress().getResultLanguageType())]
@@ -52,7 +54,9 @@ private newtype TIRDataFlowNode =
5254
use.getParameter() = p and
5355
use.getIndirectionIndex() = indirectionIndex
5456
)
55-
}
57+
} or
58+
TFinalGlobalValue(Ssa::GlobalUse globalUse) or
59+
TInitialGlobalValue(Ssa::GlobalDef globalUse)
5660

5761
/**
5862
* An operand that is defined by a `FieldAddressInstruction`.
@@ -279,7 +283,20 @@ class Node extends TIRDataFlowNode {
279283
* Gets the variable corresponding to this node, if any. This can be used for
280284
* modeling flow in and out of global variables.
281285
*/
282-
Variable asVariable() { result = this.(VariableNode).getVariable() }
286+
Variable asVariable() { this = TVariableNode(result, 1) }
287+
288+
/**
289+
* Gets the `indirectionIndex`'th indirection of this node's underlying variable, if any.
290+
*
291+
* This can be used for modeling flow in and out of global variables.
292+
*/
293+
Variable asIndirectVariable(int indirectionIndex) {
294+
indirectionIndex > 1 and
295+
this = TVariableNode(result, indirectionIndex)
296+
}
297+
298+
/** Gets an indirection of this node's underlying variable, if any. */
299+
Variable asIndirectVariable() { result = this.asIndirectVariable(_) }
283300

284301
/**
285302
* Gets the expression that is partially defined by this node, if any.
@@ -509,6 +526,66 @@ class SideEffectOperandNode extends Node, IndirectOperand {
509526
Expr getArgument() { result = call.getArgument(argumentIndex).getUnconvertedResultExpression() }
510527
}
511528

529+
/**
530+
* INTERNAL: do not use.
531+
*
532+
* A node representing the value of a global variable just before returning
533+
* from a function body.
534+
*/
535+
class FinalGlobalValue extends Node, TFinalGlobalValue {
536+
Ssa::GlobalUse globalUse;
537+
538+
FinalGlobalValue() { this = TFinalGlobalValue(globalUse) }
539+
540+
/** Gets the underlying SSA use. */
541+
Ssa::GlobalUse getGlobalUse() { result = globalUse }
542+
543+
override Declaration getEnclosingCallable() { result = this.getFunction() }
544+
545+
override Declaration getFunction() { result = globalUse.getIRFunction().getFunction() }
546+
547+
override DataFlowType getType() {
548+
exists(int indirectionIndex |
549+
indirectionIndex = globalUse.getIndirectionIndex() and
550+
result = getTypeImpl(globalUse.getUnspecifiedType(), indirectionIndex - 1)
551+
)
552+
}
553+
554+
final override Location getLocationImpl() { result = globalUse.getLocation() }
555+
556+
override string toStringImpl() { result = globalUse.toString() }
557+
}
558+
559+
/**
560+
* INTERNAL: do not use.
561+
*
562+
* A node representing the value of a global variable just after entering
563+
* a function body.
564+
*/
565+
class InitialGlobalValue extends Node, TInitialGlobalValue {
566+
Ssa::GlobalDef globalDef;
567+
568+
InitialGlobalValue() { this = TInitialGlobalValue(globalDef) }
569+
570+
/** Gets the underlying SSA definition. */
571+
Ssa::GlobalDef getGlobalDef() { result = globalDef }
572+
573+
override Declaration getEnclosingCallable() { result = this.getFunction() }
574+
575+
override Declaration getFunction() { result = globalDef.getIRFunction().getFunction() }
576+
577+
override DataFlowType getType() {
578+
exists(int indirectionIndex |
579+
indirectionIndex = globalDef.getIndirectionIndex() and
580+
result = getTypeImpl(globalDef.getUnspecifiedType(), indirectionIndex)
581+
)
582+
}
583+
584+
final override Location getLocationImpl() { result = globalDef.getLocation() }
585+
586+
override string toStringImpl() { result = globalDef.toString() }
587+
}
588+
512589
/**
513590
* INTERNAL: do not use.
514591
*
@@ -1192,12 +1269,16 @@ class DefinitionByReferenceNode extends IndirectArgumentOutNode {
11921269
*/
11931270
class VariableNode extends Node, TVariableNode {
11941271
Variable v;
1272+
int indirectionIndex;
11951273

1196-
VariableNode() { this = TVariableNode(v) }
1274+
VariableNode() { this = TVariableNode(v, indirectionIndex) }
11971275

11981276
/** Gets the variable corresponding to this node. */
11991277
Variable getVariable() { result = v }
12001278

1279+
/** Gets the indirection index of this node. */
1280+
int getIndirectionIndex() { result = indirectionIndex }
1281+
12011282
override Declaration getFunction() { none() }
12021283

12031284
override Declaration getEnclosingCallable() {
@@ -1209,11 +1290,23 @@ class VariableNode extends Node, TVariableNode {
12091290
result = v
12101291
}
12111292

1212-
override DataFlowType getType() { result = v.getType() }
1293+
override DataFlowType getType() {
1294+
result = getTypeImpl(v.getUnspecifiedType(), indirectionIndex - 1)
1295+
}
12131296

1214-
final override Location getLocationImpl() { result = v.getLocation() }
1297+
final override Location getLocationImpl() {
1298+
// Certain variables (such as parameters) can have multiple locations.
1299+
// When there's a unique location we use that one, but if multiple locations
1300+
// exist we default to an unknown location.
1301+
result = unique( | | v.getLocation())
1302+
or
1303+
not exists(unique( | | v.getLocation())) and
1304+
result instanceof UnknownDefaultLocation
1305+
}
12151306

1216-
override string toStringImpl() { result = v.toString() }
1307+
override string toStringImpl() {
1308+
if indirectionIndex = 1 then result = v.toString() else result = v.toString() + " indirection"
1309+
}
12171310
}
12181311

12191312
/**
@@ -1256,7 +1349,9 @@ DefinitionByReferenceNode definitionByReferenceNodeFromArgument(Expr argument) {
12561349
}
12571350

12581351
/** Gets the `VariableNode` corresponding to the variable `v`. */
1259-
VariableNode variableNode(Variable v) { result.getVariable() = v }
1352+
VariableNode variableNode(Variable v) {
1353+
result.getVariable() = v and result.getIndirectionIndex() = 1
1354+
}
12601355

12611356
/**
12621357
* DEPRECATED: See UninitializedNode.

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DefaultTaintTrackingImpl.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,8 @@ module TaintedWithPath {
624624

625625
private predicate isGlobalVariablePathNode(WrapPathNode n) {
626626
n.inner().getNode().asVariable() instanceof GlobalOrNamespaceVariable
627+
or
628+
n.inner().getNode().asIndirectVariable() instanceof GlobalOrNamespaceVariable
627629
}
628630

629631
private predicate edgesWithoutGlobals(PathNode a, PathNode b) {

0 commit comments

Comments
 (0)