Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 22 additions & 14 deletions cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll
Original file line number Diff line number Diff line change
Expand Up @@ -500,21 +500,25 @@ OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) {
*/
predicate jumpStep(Node n1, Node n2) {
exists(Cpp::GlobalOrNamespaceVariable v |
v =
n1.asInstruction()
.(StoreInstruction)
.getResultAddress()
.(VariableAddressInstruction)
.getAstVariable() and
v = n2.asVariable()
exists(Ssa::GlobalUse globalUse |
v = globalUse.getVariable() and
n1.(FinalGlobalValue).getGlobalUse() = globalUse
|
globalUse.getIndirectionIndex() = 1 and
v = n2.asVariable()
or
v = n2.asIndirectVariable(globalUse.getIndirectionIndex())
)
or
v =
n2.asInstruction()
.(LoadInstruction)
.getSourceAddress()
.(VariableAddressInstruction)
.getAstVariable() and
v = n1.asVariable()
exists(Ssa::GlobalDef globalDef |
v = globalDef.getVariable() and
n2.(InitialGlobalValue).getGlobalDef() = globalDef
|
globalDef.getIndirectionIndex() = 1 and
v = n1.asVariable()
or
v = n1.asIndirectVariable(globalDef.getIndirectionIndex())
)
)
}

Expand Down Expand Up @@ -696,6 +700,10 @@ predicate nodeIsHidden(Node n) {
n instanceof OperandNode and
not n instanceof ArgumentNode and
not n.asOperand() instanceof StoreValueOperand
or
n instanceof FinalGlobalValue
or
n instanceof InitialGlobalValue
}

class LambdaCallKind = Unit;
Expand Down
111 changes: 103 additions & 8 deletions cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ private import DataFlowImplCommon as DataFlowImplCommon
cached
private newtype TIRDataFlowNode =
TNode0(Node0Impl node) { DataFlowImplCommon::forceCachingInSameStage() } or
TVariableNode(Variable var) or
TVariableNode(Variable var, int indirectionIndex) {
indirectionIndex = [1 .. Ssa::getMaxIndirectionsForType(var.getUnspecifiedType())]
} or
TPostFieldUpdateNode(FieldAddress operand, int indirectionIndex) {
indirectionIndex =
[1 .. Ssa::countIndirectionsForCppType(operand.getObjectAddress().getResultLanguageType())]
Expand All @@ -52,7 +54,9 @@ private newtype TIRDataFlowNode =
use.getParameter() = p and
use.getIndirectionIndex() = indirectionIndex
)
}
} or
TFinalGlobalValue(Ssa::GlobalUse globalUse) or
TInitialGlobalValue(Ssa::GlobalDef globalUse)

/**
* An operand that is defined by a `FieldAddressInstruction`.
Expand Down Expand Up @@ -279,7 +283,20 @@ class Node extends TIRDataFlowNode {
* Gets the variable corresponding to this node, if any. This can be used for
* modeling flow in and out of global variables.
*/
Variable asVariable() { result = this.(VariableNode).getVariable() }
Variable asVariable() { this = TVariableNode(result, 1) }

/**
* Gets the `indirectionIndex`'th indirection of this node's underlying variable, if any.
*
* This can be used for modeling flow in and out of global variables.
*/
Variable asIndirectVariable(int indirectionIndex) {
indirectionIndex > 1 and
this = TVariableNode(result, indirectionIndex)
}

/** Gets an indirection of this node's underlying variable, if any. */
Variable asIndirectVariable() { result = this.asIndirectVariable(_) }

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

/**
* INTERNAL: do not use.
*
* A node representing the value of a global variable just before returning
* from a function body.
*/
class FinalGlobalValue extends Node, TFinalGlobalValue {
Ssa::GlobalUse globalUse;

FinalGlobalValue() { this = TFinalGlobalValue(globalUse) }

/** Gets the underlying SSA use. */
Ssa::GlobalUse getGlobalUse() { result = globalUse }

override Declaration getEnclosingCallable() { result = this.getFunction() }

override Declaration getFunction() { result = globalUse.getIRFunction().getFunction() }

override DataFlowType getType() {
exists(int indirectionIndex |
indirectionIndex = globalUse.getIndirectionIndex() and
result = getTypeImpl(globalUse.getUnspecifiedType(), indirectionIndex - 1)
)
}

final override Location getLocationImpl() { result = globalUse.getLocation() }

override string toStringImpl() { result = globalUse.toString() }
}

/**
* INTERNAL: do not use.
*
* A node representing the value of a global variable just after entering
* a function body.
*/
class InitialGlobalValue extends Node, TInitialGlobalValue {
Ssa::GlobalDef globalDef;

InitialGlobalValue() { this = TInitialGlobalValue(globalDef) }

/** Gets the underlying SSA definition. */
Ssa::GlobalDef getGlobalDef() { result = globalDef }

override Declaration getEnclosingCallable() { result = this.getFunction() }

override Declaration getFunction() { result = globalDef.getIRFunction().getFunction() }

override DataFlowType getType() {
exists(int indirectionIndex |
indirectionIndex = globalDef.getIndirectionIndex() and
result = getTypeImpl(globalDef.getUnspecifiedType(), indirectionIndex)
)
}

final override Location getLocationImpl() { result = globalDef.getLocation() }

override string toStringImpl() { result = globalDef.toString() }
}

/**
* INTERNAL: do not use.
*
Expand Down Expand Up @@ -1192,12 +1269,16 @@ class DefinitionByReferenceNode extends IndirectArgumentOutNode {
*/
class VariableNode extends Node, TVariableNode {
Variable v;
int indirectionIndex;

VariableNode() { this = TVariableNode(v) }
VariableNode() { this = TVariableNode(v, indirectionIndex) }

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

/** Gets the indirection index of this node. */
int getIndirectionIndex() { result = indirectionIndex }

override Declaration getFunction() { none() }

override Declaration getEnclosingCallable() {
Expand All @@ -1209,11 +1290,23 @@ class VariableNode extends Node, TVariableNode {
result = v
}

override DataFlowType getType() { result = v.getType() }
override DataFlowType getType() {
result = getTypeImpl(v.getUnspecifiedType(), indirectionIndex - 1)
}

final override Location getLocationImpl() { result = v.getLocation() }
final override Location getLocationImpl() {
// Certain variables (such as parameters) can have multiple locations.
// When there's a unique location we use that one, but if multiple locations
// exist we default to an unknown location.
result = unique( | | v.getLocation())
or
not exists(unique( | | v.getLocation())) and
result instanceof UnknownDefaultLocation
Comment on lines +1303 to +1304
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not for this PR (and I don't know how relevant this is for the user), but if this is about parameters of functions shouldn't we just pick the one associated with the actual definition of the function (and not of any of its declarations)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's probably a much better approach. I'll create an issue for this.

}

override string toStringImpl() { result = v.toString() }
override string toStringImpl() {
if indirectionIndex = 1 then result = v.toString() else result = v.toString() + " indirection"
}
}

/**
Expand Down Expand Up @@ -1256,7 +1349,9 @@ DefinitionByReferenceNode definitionByReferenceNodeFromArgument(Expr argument) {
}

/** Gets the `VariableNode` corresponding to the variable `v`. */
VariableNode variableNode(Variable v) { result.getVariable() = v }
VariableNode variableNode(Variable v) {
result.getVariable() = v and result.getIndirectionIndex() = 1
}

/**
* DEPRECATED: See UninitializedNode.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,8 @@ module TaintedWithPath {

private predicate isGlobalVariablePathNode(WrapPathNode n) {
n.inner().getNode().asVariable() instanceof GlobalOrNamespaceVariable
or
n.inner().getNode().asIndirectVariable() instanceof GlobalOrNamespaceVariable
}

private predicate edgesWithoutGlobals(PathNode a, PathNode b) {
Expand Down
Loading