Skip to content

Commit b615e98

Browse files
authored
Merge pull request github#13425 from MathiasVP/fix-more-conflation-in-dataflow
2 parents d3bc99a + 79fb6a6 commit b615e98

File tree

16 files changed

+232
-97
lines changed

16 files changed

+232
-97
lines changed

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

Lines changed: 69 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -193,86 +193,89 @@ private class SingleUseOperandNode0 extends OperandNode0, TSingleUseOperandNode0
193193
SingleUseOperandNode0() { this = TSingleUseOperandNode0(op) }
194194
}
195195

196-
/**
197-
* INTERNAL: Do not use.
198-
*
199-
* A node that represents the indirect value of an operand in the IR
200-
* after `index` number of loads.
201-
*
202-
* Note: Unlike `RawIndirectOperand`, a value of type `IndirectOperand` may
203-
* be an `OperandNode`.
204-
*/
205-
class IndirectOperand extends Node {
206-
Operand operand;
207-
int indirectionIndex;
196+
private module IndirectOperands {
197+
/**
198+
* INTERNAL: Do not use.
199+
*
200+
* A node that represents the indirect value of an operand in the IR
201+
* after `index` number of loads.
202+
*
203+
* Note: Unlike `RawIndirectOperand`, a value of type `IndirectOperand` may
204+
* be an `OperandNode`.
205+
*/
206+
abstract class IndirectOperand extends Node {
207+
/** Gets the underlying operand and the underlying indirection index. */
208+
abstract predicate hasOperandAndIndirectionIndex(Operand operand, int indirectionIndex);
209+
}
208210

209-
IndirectOperand() {
210-
this.(RawIndirectOperand).getOperand() = operand and
211-
this.(RawIndirectOperand).getIndirectionIndex() = indirectionIndex
212-
or
213-
nodeHasOperand(this, Ssa::getIRRepresentationOfIndirectOperand(operand, indirectionIndex),
214-
indirectionIndex - 1)
211+
private class IndirectOperandFromRaw extends IndirectOperand instanceof RawIndirectOperand {
212+
override predicate hasOperandAndIndirectionIndex(Operand operand, int indirectionIndex) {
213+
operand = RawIndirectOperand.super.getOperand() and
214+
indirectionIndex = RawIndirectOperand.super.getIndirectionIndex()
215+
}
215216
}
216217

217-
/** Gets the underlying operand. */
218-
Operand getOperand() { result = operand }
218+
private class IndirectOperandFromIRRepr extends IndirectOperand {
219+
Operand operand;
220+
int indirectionIndex;
219221

220-
/** Gets the underlying indirection index. */
221-
int getIndirectionIndex() { result = indirectionIndex }
222+
IndirectOperandFromIRRepr() {
223+
exists(Operand repr |
224+
repr = Ssa::getIRRepresentationOfIndirectOperand(operand, indirectionIndex) and
225+
nodeHasOperand(this, repr, indirectionIndex - 1)
226+
)
227+
}
222228

223-
/**
224-
* Holds if this `IndirectOperand` is represented directly in the IR instead of
225-
* a `RawIndirectionOperand` with operand `op` and indirection index `index`.
226-
*/
227-
predicate isIRRepresentationOf(Operand op, int index) {
228-
this instanceof OperandNode and
229-
(
230-
op = operand and
231-
index = indirectionIndex
232-
)
229+
override predicate hasOperandAndIndirectionIndex(Operand op, int index) {
230+
op = operand and index = indirectionIndex
231+
}
233232
}
234233
}
235234

236-
/**
237-
* INTERNAL: Do not use.
238-
*
239-
* A node that represents the indirect value of an instruction in the IR
240-
* after `index` number of loads.
241-
*
242-
* Note: Unlike `RawIndirectInstruction`, a value of type `IndirectInstruction` may
243-
* be an `InstructionNode`.
244-
*/
245-
class IndirectInstruction extends Node {
246-
Instruction instr;
247-
int indirectionIndex;
235+
import IndirectOperands
248236

249-
IndirectInstruction() {
250-
this.(RawIndirectInstruction).getInstruction() = instr and
251-
this.(RawIndirectInstruction).getIndirectionIndex() = indirectionIndex
252-
or
253-
nodeHasInstruction(this, Ssa::getIRRepresentationOfIndirectInstruction(instr, indirectionIndex),
254-
indirectionIndex - 1)
237+
private module IndirectInstructions {
238+
/**
239+
* INTERNAL: Do not use.
240+
*
241+
* A node that represents the indirect value of an instruction in the IR
242+
* after `index` number of loads.
243+
*
244+
* Note: Unlike `RawIndirectInstruction`, a value of type `IndirectInstruction` may
245+
* be an `InstructionNode`.
246+
*/
247+
abstract class IndirectInstruction extends Node {
248+
/** Gets the underlying operand and the underlying indirection index. */
249+
abstract predicate hasInstructionAndIndirectionIndex(Instruction instr, int index);
255250
}
256251

257-
/** Gets the underlying instruction. */
258-
Instruction getInstruction() { result = instr }
252+
private class IndirectInstructionFromRaw extends IndirectInstruction instanceof RawIndirectInstruction
253+
{
254+
override predicate hasInstructionAndIndirectionIndex(Instruction instr, int index) {
255+
instr = RawIndirectInstruction.super.getInstruction() and
256+
index = RawIndirectInstruction.super.getIndirectionIndex()
257+
}
258+
}
259259

260-
/** Gets the underlying indirection index. */
261-
int getIndirectionIndex() { result = indirectionIndex }
260+
private class IndirectInstructionFromIRRepr extends IndirectInstruction {
261+
Instruction instr;
262+
int indirectionIndex;
262263

263-
/**
264-
* Holds if this `IndirectInstruction` is represented directly in the IR instead of
265-
* a `RawIndirectionInstruction` with instruction `i` and indirection index `index`.
266-
*/
267-
predicate isIRRepresentationOf(Instruction i, int index) {
268-
this instanceof InstructionNode and
269-
(
270-
i = instr and
271-
index = indirectionIndex
272-
)
264+
IndirectInstructionFromIRRepr() {
265+
exists(Instruction repr |
266+
repr = Ssa::getIRRepresentationOfIndirectInstruction(instr, indirectionIndex) and
267+
nodeHasInstruction(this, repr, indirectionIndex - 1)
268+
)
269+
}
270+
271+
override predicate hasInstructionAndIndirectionIndex(Instruction i, int index) {
272+
i = instr and index = indirectionIndex
273+
}
273274
}
274275
}
275276

277+
import IndirectInstructions
278+
276279
/** Gets the callable in which this node occurs. */
277280
DataFlowCallable nodeGetEnclosingCallable(Node n) { result = n.getEnclosingCallable() }
278281

@@ -320,7 +323,7 @@ private class SideEffectArgumentNode extends ArgumentNode, SideEffectOperandNode
320323
override predicate argumentOf(DataFlowCall dfCall, ArgumentPosition pos) {
321324
this.getCallInstruction() = dfCall and
322325
pos.(IndirectionPosition).getArgumentIndex() = this.getArgumentIndex() and
323-
pos.(IndirectionPosition).getIndirectionIndex() = super.getIndirectionIndex()
326+
super.hasAddressOperandAndIndirectionIndex(_, pos.(IndirectionPosition).getIndirectionIndex())
324327
}
325328
}
326329

@@ -845,7 +848,7 @@ predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preserves
845848
* One example would be to allow flow like `p.foo = p.bar;`, which is disallowed
846849
* by default as a heuristic.
847850
*/
848-
predicate allowParameterReturnInSelf(ParameterNode p) { none() }
851+
predicate allowParameterReturnInSelf(ParameterNode p) { p instanceof IndirectParameterNode }
849852

850853
private predicate fieldHasApproxName(Field f, string s) {
851854
s = f.getName().charAt(0) and

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

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ class Node extends TIRDataFlowNode {
274274
* represents the value of `**x` going into `f`.
275275
*/
276276
Expr asIndirectArgument(int index) {
277-
this.(SideEffectOperandNode).getIndirectionIndex() = index and
277+
this.(SideEffectOperandNode).hasAddressOperandAndIndirectionIndex(_, index) and
278278
result = this.(SideEffectOperandNode).getArgument()
279279
}
280280

@@ -317,7 +317,7 @@ class Node extends TIRDataFlowNode {
317317
index = 0 and
318318
result = this.(ExplicitParameterNode).getParameter()
319319
or
320-
this.(IndirectParameterNode).getIndirectionIndex() = index and
320+
this.(IndirectParameterNode).hasInstructionAndIndirectionIndex(_, index) and
321321
result = this.(IndirectParameterNode).getParameter()
322322
}
323323

@@ -577,15 +577,20 @@ class SsaPhiNode extends Node, TSsaPhiNode {
577577
*
578578
* A node representing a value after leaving a function.
579579
*/
580-
class SideEffectOperandNode extends Node, IndirectOperand {
580+
class SideEffectOperandNode extends Node instanceof IndirectOperand {
581581
CallInstruction call;
582582
int argumentIndex;
583583

584-
SideEffectOperandNode() { operand = call.getArgumentOperand(argumentIndex) }
584+
SideEffectOperandNode() {
585+
IndirectOperand.super.hasOperandAndIndirectionIndex(call.getArgumentOperand(argumentIndex), _)
586+
}
585587

586588
CallInstruction getCallInstruction() { result = call }
587589

588-
Operand getAddressOperand() { result = operand }
590+
/** Gets the underlying operand and the underlying indirection index. */
591+
predicate hasAddressOperandAndIndirectionIndex(Operand operand, int indirectionIndex) {
592+
IndirectOperand.super.hasOperandAndIndirectionIndex(operand, indirectionIndex)
593+
}
589594

590595
int getArgumentIndex() { result = argumentIndex }
591596

@@ -665,10 +670,10 @@ class InitialGlobalValue extends Node, TInitialGlobalValue {
665670
*
666671
* A node representing an indirection of a parameter.
667672
*/
668-
class IndirectParameterNode extends Node, IndirectInstruction {
673+
class IndirectParameterNode extends Node instanceof IndirectInstruction {
669674
InitializeParameterInstruction init;
670675

671-
IndirectParameterNode() { this.getInstruction() = init }
676+
IndirectParameterNode() { IndirectInstruction.super.hasInstructionAndIndirectionIndex(init, _) }
672677

673678
int getArgumentIndex() { init.hasIndex(result) }
674679

@@ -677,7 +682,12 @@ class IndirectParameterNode extends Node, IndirectInstruction {
677682

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

680-
override Declaration getFunction() { result = this.getInstruction().getEnclosingFunction() }
685+
override Declaration getFunction() { result = init.getEnclosingFunction() }
686+
687+
/** Gets the underlying operand and the underlying indirection index. */
688+
predicate hasInstructionAndIndirectionIndex(Instruction instr, int index) {
689+
IndirectInstruction.super.hasInstructionAndIndirectionIndex(instr, index)
690+
}
681691

682692
override Location getLocationImpl() { result = this.getParameter().getLocation() }
683693

@@ -699,7 +709,8 @@ class IndirectReturnNode extends Node {
699709
IndirectReturnNode() {
700710
this instanceof FinalParameterNode
701711
or
702-
this.(IndirectOperand).getOperand() = any(ReturnValueInstruction ret).getReturnAddressOperand()
712+
this.(IndirectOperand)
713+
.hasOperandAndIndirectionIndex(any(ReturnValueInstruction ret).getReturnAddressOperand(), _)
703714
}
704715

705716
override Declaration getEnclosingCallable() { result = this.getFunction() }
@@ -722,7 +733,7 @@ class IndirectReturnNode extends Node {
722733
int getIndirectionIndex() {
723734
result = this.(FinalParameterNode).getIndirectionIndex()
724735
or
725-
result = this.(IndirectOperand).getIndirectionIndex()
736+
this.(IndirectOperand).hasOperandAndIndirectionIndex(_, result)
726737
}
727738
}
728739

@@ -1106,7 +1117,8 @@ predicate exprNodeShouldBeInstruction(Node node, Expr e) {
11061117
/** Holds if `node` should be an `IndirectInstruction` that maps `node.asIndirectExpr()` to `e`. */
11071118
predicate indirectExprNodeShouldBeIndirectInstruction(IndirectInstruction node, Expr e) {
11081119
exists(Instruction instr |
1109-
instr = node.getInstruction() and not indirectExprNodeShouldBeIndirectOperand(_, e)
1120+
node.hasInstructionAndIndirectionIndex(instr, _) and
1121+
not indirectExprNodeShouldBeIndirectOperand(_, e)
11101122
|
11111123
e = instr.(VariableAddressInstruction).getAst().(Expr).getFullyConverted()
11121124
or
@@ -1307,8 +1319,8 @@ pragma[noinline]
13071319
private predicate indirectParameterNodeHasArgumentIndexAndIndex(
13081320
IndirectParameterNode node, int argumentIndex, int indirectionIndex
13091321
) {
1310-
node.getArgumentIndex() = argumentIndex and
1311-
node.getIndirectionIndex() = indirectionIndex
1322+
node.hasInstructionAndIndirectionIndex(_, indirectionIndex) and
1323+
node.getArgumentIndex() = argumentIndex
13121324
}
13131325

13141326
/** A synthetic parameter to model the pointed-to object of a pointer parameter. */
@@ -1479,18 +1491,14 @@ VariableNode variableNode(Variable v) {
14791491
*/
14801492
Node uninitializedNode(LocalVariable v) { none() }
14811493

1482-
pragma[noinline]
14831494
predicate hasOperandAndIndex(IndirectOperand indirectOperand, Operand operand, int indirectionIndex) {
1484-
indirectOperand.getOperand() = operand and
1485-
indirectOperand.getIndirectionIndex() = indirectionIndex
1495+
indirectOperand.hasOperandAndIndirectionIndex(operand, indirectionIndex)
14861496
}
14871497

1488-
pragma[noinline]
14891498
predicate hasInstructionAndIndex(
14901499
IndirectInstruction indirectInstr, Instruction instr, int indirectionIndex
14911500
) {
1492-
indirectInstr.getInstruction() = instr and
1493-
indirectInstr.getIndirectionIndex() = indirectionIndex
1501+
indirectInstr.hasInstructionAndIndirectionIndex(instr, indirectionIndex)
14941502
}
14951503

14961504
cached
@@ -1656,8 +1664,7 @@ module ExprFlowCached {
16561664
private predicate isIndirectBaseOfArrayAccess(IndirectOperand n, Expr e) {
16571665
exists(LoadInstruction load, PointerArithmeticInstruction pai |
16581666
pai = load.getSourceAddress() and
1659-
pai.getLeftOperand() = n.getOperand() and
1660-
n.getIndirectionIndex() = 1 and
1667+
n.hasOperandAndIndirectionIndex(pai.getLeftOperand(), 1) and
16611668
e = load.getConvertedResultExpression()
16621669
)
16631670
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class FieldFlowPropertyProvider extends IRPropertyProvider {
1313
override string getOperandProperty(Operand operand, string key) {
1414
exists(PostFieldUpdateNode pfun, Content content |
1515
key = "store " + content.toString() and
16-
operand = pfun.getPreUpdateNode().(IndirectOperand).getOperand() and
16+
pfun.getPreUpdateNode().(IndirectOperand).hasOperandAndIndirectionIndex(operand, _) and
1717
result =
1818
strictconcat(string element, Node node |
1919
storeStep(node, content, pfun) and
@@ -25,7 +25,7 @@ class FieldFlowPropertyProvider extends IRPropertyProvider {
2525
or
2626
exists(Node node2, Content content |
2727
key = "read " + content.toString() and
28-
operand = node2.(IndirectOperand).getOperand() and
28+
node2.(IndirectOperand).hasOperandAndIndirectionIndex(operand, _) and
2929
result =
3030
strictconcat(string element, Node node1 |
3131
readStep(node1, content, node2) and

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,12 @@ private string stars(int k) {
1818
}
1919

2020
string starsForNode(Node node) {
21-
result = stars(node.(IndirectInstruction).getIndirectionIndex())
22-
or
23-
result = stars(node.(IndirectOperand).getIndirectionIndex())
21+
exists(int indirectionIndex |
22+
node.(IndirectInstruction).hasInstructionAndIndirectionIndex(_, indirectionIndex) or
23+
node.(IndirectOperand).hasOperandAndIndirectionIndex(_, indirectionIndex)
24+
|
25+
result = stars(indirectionIndex)
26+
)
2427
or
2528
not node instanceof IndirectInstruction and
2629
not node instanceof IndirectOperand and

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ private module IteratorIndirections {
263263
// Taint through `operator+=` and `operator-=` on iterators.
264264
call.getStaticCallTarget() instanceof Iterator::IteratorAssignArithmeticOperator and
265265
node2.(IndirectArgumentOutNode).getPreUpdateNode() = node1 and
266-
node1.(IndirectOperand).getOperand() = call.getArgumentOperand(0) and
266+
node1.(IndirectOperand).hasOperandAndIndirectionIndex(call.getArgumentOperand(0), _) and
267267
node1.getType().getUnspecifiedType() = this
268268
)
269269
}
@@ -796,7 +796,7 @@ private module Cached {
796796
address.getDef() = instr and
797797
isDereference(load, address) and
798798
isUseImpl(address, _, indirectionIndex - 1) and
799-
result = instr
799+
result = load
800800
)
801801
}
802802

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ predicate modeledTaintStep(DataFlow::Node nodeIn, DataFlow::Node nodeOut) {
160160
FunctionInput modelIn, FunctionOutput modelOut
161161
|
162162
indirectArgument = callInput(call, modelIn) and
163-
indirectArgument.getAddressOperand() = nodeIn.asOperand() and
163+
indirectArgument.hasAddressOperandAndIndirectionIndex(nodeIn.asOperand(), _) and
164164
call.getStaticCallTarget() = func and
165165
(
166166
func.(DataFlowFunction).hasDataFlow(modelIn, modelOut)

cpp/ql/lib/semmle/code/cpp/models/implementations/Strcpy.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, Sid
108108
// these may do only a partial copy of the input buffer to the output
109109
// buffer
110110
exists(this.getParamSize()) and
111-
input.isParameter(this.getParamSrc()) and
111+
input.isParameterDeref(this.getParamSrc()) and
112112
(
113113
output.isParameterDeref(this.getParamDest()) or
114114
output.isReturnValueDeref()

0 commit comments

Comments
 (0)