Skip to content

Commit 66f4ecc

Browse files
authored
Merge pull request github#14632 from MathiasVP/share-ipa-numbering-for-indirect-nodes
C++: Share IPA numbering for indirect nodes
2 parents 435b7df + b4958e7 commit 66f4ecc

File tree

6 files changed

+156
-161
lines changed

6 files changed

+156
-161
lines changed

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

Lines changed: 156 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,12 @@ private newtype TIRDataFlowNode =
4444
TIndirectArgumentOutNode(ArgumentOperand operand, int indirectionIndex) {
4545
Ssa::isModifiableByCall(operand, indirectionIndex)
4646
} or
47-
TRawIndirectOperand(Operand op, int indirectionIndex) {
48-
Ssa::hasRawIndirectOperand(op, indirectionIndex)
47+
TRawIndirectOperand0(Node0Impl node, int indirectionIndex) {
48+
Ssa::hasRawIndirectOperand(node.asOperand(), indirectionIndex)
4949
} or
50-
TRawIndirectInstruction(Instruction instr, int indirectionIndex) {
51-
Ssa::hasRawIndirectInstruction(instr, indirectionIndex)
50+
TRawIndirectInstruction0(Node0Impl node, int indirectionIndex) {
51+
not exists(node.asOperand()) and
52+
Ssa::hasRawIndirectInstruction(node.asInstruction(), indirectionIndex)
5253
} or
5354
TFinalParameterNode(Parameter p, int indirectionIndex) {
5455
exists(Ssa::FinalParameterUse use |
@@ -918,48 +919,146 @@ Type getTypeImpl(Type t, int indirectionIndex) {
918919
result instanceof UnknownType
919920
}
920921

921-
/**
922-
* INTERNAL: Do not use.
923-
*
924-
* A node that represents the indirect value of an operand in the IR
925-
* after `index` number of loads.
926-
*/
927-
class RawIndirectOperand extends Node, TRawIndirectOperand {
928-
Operand operand;
929-
int indirectionIndex;
922+
private module RawIndirectNodes {
923+
/**
924+
* INTERNAL: Do not use.
925+
*
926+
* A node that represents the indirect value of an operand in the IR
927+
* after `index` number of loads.
928+
*/
929+
private class RawIndirectOperand0 extends Node, TRawIndirectOperand0 {
930+
Node0Impl node;
931+
int indirectionIndex;
930932

931-
RawIndirectOperand() { this = TRawIndirectOperand(operand, indirectionIndex) }
933+
RawIndirectOperand0() { this = TRawIndirectOperand0(node, indirectionIndex) }
932934

933-
/** Gets the underlying instruction. */
934-
Operand getOperand() { result = operand }
935+
/** Gets the underlying instruction. */
936+
Operand getOperand() { result = node.asOperand() }
935937

936-
/** Gets the underlying indirection index. */
937-
int getIndirectionIndex() { result = indirectionIndex }
938+
/** Gets the underlying indirection index. */
939+
int getIndirectionIndex() { result = indirectionIndex }
938940

939-
override Declaration getFunction() { result = this.getOperand().getDef().getEnclosingFunction() }
941+
override Declaration getFunction() {
942+
result = this.getOperand().getDef().getEnclosingFunction()
943+
}
940944

941-
override Declaration getEnclosingCallable() { result = this.getFunction() }
945+
override Declaration getEnclosingCallable() { result = this.getFunction() }
942946

943-
override DataFlowType getType() {
944-
exists(int sub, DataFlowType type, boolean isGLValue |
945-
type = getOperandType(operand, isGLValue) and
946-
if isGLValue = true then sub = 1 else sub = 0
947-
|
948-
result = getTypeImpl(type.getUnspecifiedType(), indirectionIndex - sub)
949-
)
947+
override DataFlowType getType() {
948+
exists(int sub, DataFlowType type, boolean isGLValue |
949+
type = getOperandType(this.getOperand(), isGLValue) and
950+
if isGLValue = true then sub = 1 else sub = 0
951+
|
952+
result = getTypeImpl(type.getUnspecifiedType(), indirectionIndex - sub)
953+
)
954+
}
955+
956+
final override Location getLocationImpl() {
957+
if exists(this.getOperand().getLocation())
958+
then result = this.getOperand().getLocation()
959+
else result instanceof UnknownDefaultLocation
960+
}
961+
962+
override string toStringImpl() {
963+
result = operandNode(this.getOperand()).toStringImpl() + " indirection"
964+
}
950965
}
951966

952-
final override Location getLocationImpl() {
953-
if exists(this.getOperand().getLocation())
954-
then result = this.getOperand().getLocation()
955-
else result instanceof UnknownDefaultLocation
967+
/**
968+
* INTERNAL: Do not use.
969+
*
970+
* A node that represents the indirect value of an instruction in the IR
971+
* after `index` number of loads.
972+
*/
973+
private class RawIndirectInstruction0 extends Node, TRawIndirectInstruction0 {
974+
Node0Impl node;
975+
int indirectionIndex;
976+
977+
RawIndirectInstruction0() { this = TRawIndirectInstruction0(node, indirectionIndex) }
978+
979+
/** Gets the underlying instruction. */
980+
Instruction getInstruction() { result = node.asInstruction() }
981+
982+
/** Gets the underlying indirection index. */
983+
int getIndirectionIndex() { result = indirectionIndex }
984+
985+
override Declaration getFunction() { result = this.getInstruction().getEnclosingFunction() }
986+
987+
override Declaration getEnclosingCallable() { result = this.getFunction() }
988+
989+
override DataFlowType getType() {
990+
exists(int sub, DataFlowType type, boolean isGLValue |
991+
type = getInstructionType(this.getInstruction(), isGLValue) and
992+
if isGLValue = true then sub = 1 else sub = 0
993+
|
994+
result = getTypeImpl(type.getUnspecifiedType(), indirectionIndex - sub)
995+
)
996+
}
997+
998+
final override Location getLocationImpl() {
999+
if exists(this.getInstruction().getLocation())
1000+
then result = this.getInstruction().getLocation()
1001+
else result instanceof UnknownDefaultLocation
1002+
}
1003+
1004+
override string toStringImpl() {
1005+
result = instructionNode(this.getInstruction()).toStringImpl() + " indirection"
1006+
}
9561007
}
9571008

958-
override string toStringImpl() {
959-
result = operandNode(this.getOperand()).toStringImpl() + " indirection"
1009+
/**
1010+
* INTERNAL: Do not use.
1011+
*
1012+
* A node that represents the indirect value of an operand in the IR
1013+
* after a number of loads.
1014+
*/
1015+
class RawIndirectOperand extends Node {
1016+
int indirectionIndex;
1017+
Operand operand;
1018+
1019+
RawIndirectOperand() {
1020+
exists(Node0Impl node | operand = node.asOperand() |
1021+
this = TRawIndirectOperand0(node, indirectionIndex)
1022+
or
1023+
this = TRawIndirectInstruction0(node, indirectionIndex)
1024+
)
1025+
}
1026+
1027+
/** Gets the operand associated with this node. */
1028+
Operand getOperand() { result = operand }
1029+
1030+
/** Gets the underlying indirection index. */
1031+
int getIndirectionIndex() { result = indirectionIndex }
1032+
}
1033+
1034+
/**
1035+
* INTERNAL: Do not use.
1036+
*
1037+
* A node that represents the indirect value of an instruction in the IR
1038+
* after a number of loads.
1039+
*/
1040+
class RawIndirectInstruction extends Node {
1041+
int indirectionIndex;
1042+
Instruction instr;
1043+
1044+
RawIndirectInstruction() {
1045+
exists(Node0Impl node | instr = node.asInstruction() |
1046+
this = TRawIndirectOperand0(node, indirectionIndex)
1047+
or
1048+
this = TRawIndirectInstruction0(node, indirectionIndex)
1049+
)
1050+
}
1051+
1052+
/** Gets the instruction associated with this node. */
1053+
Instruction getInstruction() { result = instr }
1054+
1055+
/** Gets the underlying indirection index. */
1056+
int getIndirectionIndex() { result = indirectionIndex }
9601057
}
9611058
}
9621059

1060+
import RawIndirectNodes
1061+
9631062
/**
9641063
* INTERNAL: do not use.
9651064
*
@@ -1021,48 +1120,6 @@ class UninitializedNode extends Node {
10211120
LocalVariable getLocalVariable() { result = v }
10221121
}
10231122

1024-
/**
1025-
* INTERNAL: Do not use.
1026-
*
1027-
* A node that represents the indirect value of an instruction in the IR
1028-
* after `index` number of loads.
1029-
*/
1030-
class RawIndirectInstruction extends Node, TRawIndirectInstruction {
1031-
Instruction instr;
1032-
int indirectionIndex;
1033-
1034-
RawIndirectInstruction() { this = TRawIndirectInstruction(instr, indirectionIndex) }
1035-
1036-
/** Gets the underlying instruction. */
1037-
Instruction getInstruction() { result = instr }
1038-
1039-
/** Gets the underlying indirection index. */
1040-
int getIndirectionIndex() { result = indirectionIndex }
1041-
1042-
override Declaration getFunction() { result = this.getInstruction().getEnclosingFunction() }
1043-
1044-
override Declaration getEnclosingCallable() { result = this.getFunction() }
1045-
1046-
override DataFlowType getType() {
1047-
exists(int sub, DataFlowType type, boolean isGLValue |
1048-
type = getInstructionType(instr, isGLValue) and
1049-
if isGLValue = true then sub = 1 else sub = 0
1050-
|
1051-
result = getTypeImpl(type.getUnspecifiedType(), indirectionIndex - sub)
1052-
)
1053-
}
1054-
1055-
final override Location getLocationImpl() {
1056-
if exists(this.getInstruction().getLocation())
1057-
then result = this.getInstruction().getLocation()
1058-
else result instanceof UnknownDefaultLocation
1059-
}
1060-
1061-
override string toStringImpl() {
1062-
result = instructionNode(this.getInstruction()).toStringImpl() + " indirection"
1063-
}
1064-
}
1065-
10661123
private module GetConvertedResultExpression {
10671124
private import semmle.code.cpp.ir.implementation.raw.internal.TranslatedExpr
10681125
private import semmle.code.cpp.ir.implementation.raw.internal.InstructionTag
@@ -1600,26 +1657,29 @@ private module Cached {
16001657
predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFrom, nodeTo) }
16011658

16021659
private predicate indirectionOperandFlow(RawIndirectOperand nodeFrom, Node nodeTo) {
1603-
// Reduce the indirection count by 1 if we're passing through a `LoadInstruction`.
1604-
exists(int ind, LoadInstruction load |
1605-
hasOperandAndIndex(nodeFrom, load.getSourceAddressOperand(), ind) and
1606-
nodeHasInstruction(nodeTo, load, ind - 1)
1607-
)
1608-
or
1609-
// If an operand flows to an instruction, then the indirection of
1610-
// the operand also flows to the indirection of the instruction.
1611-
exists(Operand operand, Instruction instr, int indirectionIndex |
1612-
simpleInstructionLocalFlowStep(operand, instr) and
1613-
hasOperandAndIndex(nodeFrom, operand, pragma[only_bind_into](indirectionIndex)) and
1614-
hasInstructionAndIndex(nodeTo, instr, pragma[only_bind_into](indirectionIndex))
1615-
)
1616-
or
1617-
// If there's indirect flow to an operand, then there's also indirect
1618-
// flow to the operand after applying some pointer arithmetic.
1619-
exists(PointerArithmeticInstruction pointerArith, int indirectionIndex |
1620-
hasOperandAndIndex(nodeFrom, pointerArith.getAnOperand(),
1621-
pragma[only_bind_into](indirectionIndex)) and
1622-
hasInstructionAndIndex(nodeTo, pointerArith, pragma[only_bind_into](indirectionIndex))
1660+
nodeFrom != nodeTo and
1661+
(
1662+
// Reduce the indirection count by 1 if we're passing through a `LoadInstruction`.
1663+
exists(int ind, LoadInstruction load |
1664+
hasOperandAndIndex(nodeFrom, load.getSourceAddressOperand(), ind) and
1665+
nodeHasInstruction(nodeTo, load, ind - 1)
1666+
)
1667+
or
1668+
// If an operand flows to an instruction, then the indirection of
1669+
// the operand also flows to the indirection of the instruction.
1670+
exists(Operand operand, Instruction instr, int indirectionIndex |
1671+
simpleInstructionLocalFlowStep(operand, instr) and
1672+
hasOperandAndIndex(nodeFrom, operand, pragma[only_bind_into](indirectionIndex)) and
1673+
hasInstructionAndIndex(nodeTo, instr, pragma[only_bind_into](indirectionIndex))
1674+
)
1675+
or
1676+
// If there's indirect flow to an operand, then there's also indirect
1677+
// flow to the operand after applying some pointer arithmetic.
1678+
exists(PointerArithmeticInstruction pointerArith, int indirectionIndex |
1679+
hasOperandAndIndex(nodeFrom, pointerArith.getAnOperand(),
1680+
pragma[only_bind_into](indirectionIndex)) and
1681+
hasInstructionAndIndex(nodeTo, pointerArith, pragma[only_bind_into](indirectionIndex))
1682+
)
16231683
)
16241684
}
16251685

@@ -1645,6 +1705,7 @@ private module Cached {
16451705
private predicate indirectionInstructionFlow(
16461706
RawIndirectInstruction nodeFrom, IndirectOperand nodeTo
16471707
) {
1708+
nodeFrom != nodeTo and
16481709
// If there's flow from an instruction to an operand, then there's also flow from the
16491710
// indirect instruction to the indirect operand.
16501711
exists(Operand operand, Instruction instr, int indirectionIndex |

cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/array-access/ArrayAccessProductFlow.expected

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ edges
2929
| test.cpp:69:10:69:10 | arr indirection [post update] [p] | test.cpp:70:5:70:7 | arr indirection [p] |
3030
| test.cpp:69:14:69:19 | call to malloc | test.cpp:69:5:69:25 | ... = ... |
3131
| test.cpp:70:5:70:7 | arr indirection [p] | test.cpp:67:10:67:19 | mk_array_p indirection [p] |
32-
| test.cpp:70:5:70:7 | arr indirection [p] | test.cpp:70:5:70:7 | arr indirection [p] |
3332
| test.cpp:76:20:76:29 | call to mk_array_p indirection [p] | test.cpp:79:9:79:11 | arr indirection [p] |
3433
| test.cpp:76:20:76:29 | call to mk_array_p indirection [p] | test.cpp:83:9:83:11 | arr indirection [p] |
3534
| test.cpp:79:9:79:11 | arr indirection [p] | test.cpp:79:14:79:14 | p |

0 commit comments

Comments
 (0)