C++: Define indirect instructions (and operands) using a 'Node0Impl' column instead of an instruction (or operand).

This commit is contained in:
Mathias Vorreiter Pedersen
2023-10-30 11:49:26 +00:00
parent c4521a30aa
commit 535d1e2565

View File

@@ -44,11 +44,12 @@ private newtype TIRDataFlowNode =
TIndirectArgumentOutNode(ArgumentOperand operand, int indirectionIndex) { TIndirectArgumentOutNode(ArgumentOperand operand, int indirectionIndex) {
Ssa::isModifiableByCall(operand, indirectionIndex) Ssa::isModifiableByCall(operand, indirectionIndex)
} or } or
TRawIndirectOperand(Operand op, int indirectionIndex) { TRawIndirectOperand0(Node0Impl node, int indirectionIndex) {
Ssa::hasRawIndirectOperand(op, indirectionIndex) Ssa::hasRawIndirectOperand(node.asOperand(), indirectionIndex)
} or } or
TRawIndirectInstruction(Instruction instr, int indirectionIndex) { TRawIndirectInstruction0(Node0Impl node, int indirectionIndex) {
Ssa::hasRawIndirectInstruction(instr, indirectionIndex) not exists(node.asOperand()) and
Ssa::hasRawIndirectInstruction(node.asInstruction(), indirectionIndex)
} or } or
TFinalParameterNode(Parameter p, int indirectionIndex) { TFinalParameterNode(Parameter p, int indirectionIndex) {
exists(Ssa::FinalParameterUse use | exists(Ssa::FinalParameterUse use |
@@ -918,48 +919,146 @@ Type getTypeImpl(Type t, int indirectionIndex) {
result instanceof UnknownType result instanceof UnknownType
} }
/** private module RawIndirectNodes {
* INTERNAL: Do not use. /**
* * INTERNAL: Do not use.
* A node that represents the indirect value of an operand in the IR *
* after `index` number of loads. * A node that represents the indirect value of an operand in the IR
*/ * after `index` number of loads.
class RawIndirectOperand extends Node, TRawIndirectOperand { */
Operand operand; private class RawIndirectOperand0 extends Node, TRawIndirectOperand0 {
int indirectionIndex; Node0Impl node;
int indirectionIndex;
RawIndirectOperand() { this = TRawIndirectOperand(operand, indirectionIndex) } RawIndirectOperand0() { this = TRawIndirectOperand0(node, indirectionIndex) }
/** Gets the underlying instruction. */ /** Gets the underlying instruction. */
Operand getOperand() { result = operand } Operand getOperand() { result = node.asOperand() }
/** Gets the underlying indirection index. */ /** Gets the underlying indirection index. */
int getIndirectionIndex() { result = indirectionIndex } int getIndirectionIndex() { result = indirectionIndex }
override Declaration getFunction() { result = this.getOperand().getDef().getEnclosingFunction() } override Declaration getFunction() {
result = this.getOperand().getDef().getEnclosingFunction()
}
override Declaration getEnclosingCallable() { result = this.getFunction() } override Declaration getEnclosingCallable() { result = this.getFunction() }
override DataFlowType getType() { override DataFlowType getType() {
exists(int sub, DataFlowType type, boolean isGLValue | exists(int sub, DataFlowType type, boolean isGLValue |
type = getOperandType(operand, isGLValue) and type = getOperandType(this.getOperand(), isGLValue) and
if isGLValue = true then sub = 1 else sub = 0 if isGLValue = true then sub = 1 else sub = 0
| |
result = getTypeImpl(type.getUnspecifiedType(), indirectionIndex - sub) result = getTypeImpl(type.getUnspecifiedType(), indirectionIndex - sub)
) )
}
final override Location getLocationImpl() {
if exists(this.getOperand().getLocation())
then result = this.getOperand().getLocation()
else result instanceof UnknownDefaultLocation
}
override string toStringImpl() {
result = operandNode(this.getOperand()).toStringImpl() + " indirection"
}
} }
final override Location getLocationImpl() { /**
if exists(this.getOperand().getLocation()) * INTERNAL: Do not use.
then result = this.getOperand().getLocation() *
else result instanceof UnknownDefaultLocation * A node that represents the indirect value of an instruction in the IR
* after `index` number of loads.
*/
private class RawIndirectInstruction0 extends Node, TRawIndirectInstruction0 {
Node0Impl node;
int indirectionIndex;
RawIndirectInstruction0() { this = TRawIndirectInstruction0(node, indirectionIndex) }
/** Gets the underlying instruction. */
Instruction getInstruction() { result = node.asInstruction() }
/** Gets the underlying indirection index. */
int getIndirectionIndex() { result = indirectionIndex }
override Declaration getFunction() { result = this.getInstruction().getEnclosingFunction() }
override Declaration getEnclosingCallable() { result = this.getFunction() }
override DataFlowType getType() {
exists(int sub, DataFlowType type, boolean isGLValue |
type = getInstructionType(this.getInstruction(), isGLValue) and
if isGLValue = true then sub = 1 else sub = 0
|
result = getTypeImpl(type.getUnspecifiedType(), indirectionIndex - sub)
)
}
final override Location getLocationImpl() {
if exists(this.getInstruction().getLocation())
then result = this.getInstruction().getLocation()
else result instanceof UnknownDefaultLocation
}
override string toStringImpl() {
result = instructionNode(this.getInstruction()).toStringImpl() + " indirection"
}
} }
override string toStringImpl() { /**
result = operandNode(this.getOperand()).toStringImpl() + " indirection" * INTERNAL: Do not use.
*
* A node that represents the indirect value of an operand in the IR
* after a number of loads.
*/
class RawIndirectOperand extends Node {
int indirectionIndex;
Operand operand;
RawIndirectOperand() {
exists(Node0Impl node | operand = node.asOperand() |
this = TRawIndirectOperand0(node, indirectionIndex)
or
this = TRawIndirectInstruction0(node, indirectionIndex)
)
}
/** Gets the operand associated with this node. */
Operand getOperand() { result = operand }
/** Gets the underlying indirection index. */
int getIndirectionIndex() { result = indirectionIndex }
}
/**
* INTERNAL: Do not use.
*
* A node that represents the indirect value of an instruction in the IR
* after a number of loads.
*/
class RawIndirectInstruction extends Node {
int indirectionIndex;
Instruction instr;
RawIndirectInstruction() {
exists(Node0Impl node | instr = node.asInstruction() |
this = TRawIndirectOperand0(node, indirectionIndex)
or
this = TRawIndirectInstruction0(node, indirectionIndex)
)
}
/** Gets the instruction associated with this node. */
Instruction getInstruction() { result = instr }
/** Gets the underlying indirection index. */
int getIndirectionIndex() { result = indirectionIndex }
} }
} }
import RawIndirectNodes
/** /**
* INTERNAL: do not use. * INTERNAL: do not use.
* *
@@ -1021,48 +1120,6 @@ class UninitializedNode extends Node {
LocalVariable getLocalVariable() { result = v } LocalVariable getLocalVariable() { result = v }
} }
/**
* INTERNAL: Do not use.
*
* A node that represents the indirect value of an instruction in the IR
* after `index` number of loads.
*/
class RawIndirectInstruction extends Node, TRawIndirectInstruction {
Instruction instr;
int indirectionIndex;
RawIndirectInstruction() { this = TRawIndirectInstruction(instr, indirectionIndex) }
/** Gets the underlying instruction. */
Instruction getInstruction() { result = instr }
/** Gets the underlying indirection index. */
int getIndirectionIndex() { result = indirectionIndex }
override Declaration getFunction() { result = this.getInstruction().getEnclosingFunction() }
override Declaration getEnclosingCallable() { result = this.getFunction() }
override DataFlowType getType() {
exists(int sub, DataFlowType type, boolean isGLValue |
type = getInstructionType(instr, isGLValue) and
if isGLValue = true then sub = 1 else sub = 0
|
result = getTypeImpl(type.getUnspecifiedType(), indirectionIndex - sub)
)
}
final override Location getLocationImpl() {
if exists(this.getInstruction().getLocation())
then result = this.getInstruction().getLocation()
else result instanceof UnknownDefaultLocation
}
override string toStringImpl() {
result = instructionNode(this.getInstruction()).toStringImpl() + " indirection"
}
}
private module GetConvertedResultExpression { private module GetConvertedResultExpression {
private import semmle.code.cpp.ir.implementation.raw.internal.TranslatedExpr private import semmle.code.cpp.ir.implementation.raw.internal.TranslatedExpr
private import semmle.code.cpp.ir.implementation.raw.internal.InstructionTag private import semmle.code.cpp.ir.implementation.raw.internal.InstructionTag
@@ -1600,26 +1657,29 @@ private module Cached {
predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFrom, nodeTo) } predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFrom, nodeTo) }
private predicate indirectionOperandFlow(RawIndirectOperand nodeFrom, Node nodeTo) { private predicate indirectionOperandFlow(RawIndirectOperand nodeFrom, Node nodeTo) {
// Reduce the indirection count by 1 if we're passing through a `LoadInstruction`. nodeFrom != nodeTo and
exists(int ind, LoadInstruction load | (
hasOperandAndIndex(nodeFrom, load.getSourceAddressOperand(), ind) and // Reduce the indirection count by 1 if we're passing through a `LoadInstruction`.
nodeHasInstruction(nodeTo, load, ind - 1) exists(int ind, LoadInstruction load |
) hasOperandAndIndex(nodeFrom, load.getSourceAddressOperand(), ind) and
or nodeHasInstruction(nodeTo, load, ind - 1)
// If an operand flows to an instruction, then the indirection of )
// the operand also flows to the indirection of the instruction. or
exists(Operand operand, Instruction instr, int indirectionIndex | // If an operand flows to an instruction, then the indirection of
simpleInstructionLocalFlowStep(operand, instr) and // the operand also flows to the indirection of the instruction.
hasOperandAndIndex(nodeFrom, operand, pragma[only_bind_into](indirectionIndex)) and exists(Operand operand, Instruction instr, int indirectionIndex |
hasInstructionAndIndex(nodeTo, instr, pragma[only_bind_into](indirectionIndex)) simpleInstructionLocalFlowStep(operand, instr) and
) hasOperandAndIndex(nodeFrom, operand, pragma[only_bind_into](indirectionIndex)) and
or hasInstructionAndIndex(nodeTo, instr, pragma[only_bind_into](indirectionIndex))
// If there's indirect flow to an operand, then there's also indirect )
// flow to the operand after applying some pointer arithmetic. or
exists(PointerArithmeticInstruction pointerArith, int indirectionIndex | // If there's indirect flow to an operand, then there's also indirect
hasOperandAndIndex(nodeFrom, pointerArith.getAnOperand(), // flow to the operand after applying some pointer arithmetic.
pragma[only_bind_into](indirectionIndex)) and exists(PointerArithmeticInstruction pointerArith, int indirectionIndex |
hasInstructionAndIndex(nodeTo, pointerArith, pragma[only_bind_into](indirectionIndex)) hasOperandAndIndex(nodeFrom, pointerArith.getAnOperand(),
pragma[only_bind_into](indirectionIndex)) and
hasInstructionAndIndex(nodeTo, pointerArith, pragma[only_bind_into](indirectionIndex))
)
) )
} }
@@ -1645,6 +1705,7 @@ private module Cached {
private predicate indirectionInstructionFlow( private predicate indirectionInstructionFlow(
RawIndirectInstruction nodeFrom, IndirectOperand nodeTo RawIndirectInstruction nodeFrom, IndirectOperand nodeTo
) { ) {
nodeFrom != nodeTo and
// If there's flow from an instruction to an operand, then there's also flow from the // If there's flow from an instruction to an operand, then there's also flow from the
// indirect instruction to the indirect operand. // indirect instruction to the indirect operand.
exists(Operand operand, Instruction instr, int indirectionIndex | exists(Operand operand, Instruction instr, int indirectionIndex |