Skip to content

Commit 834263f

Browse files
committed
C++: Alternate instruction -> operand flow
1 parent 777dc63 commit 834263f

File tree

1 file changed

+29
-31
lines changed

1 file changed

+29
-31
lines changed

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

Lines changed: 29 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -508,11 +508,11 @@ predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFr
508508
* data flow. It may have less flow than the `localFlowStep` predicate.
509509
*/
510510
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
511-
// Instruction -> Instruction flow
512-
simpleInstructionLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asInstruction())
513-
or
514511
// Operand -> Instruction flow
515-
simpleOperandLocalFlowStep(nodeFrom.asOperand(), nodeTo.asInstruction())
512+
simpleInstructionLocalFlowStep(nodeFrom.asOperand(), nodeTo.asInstruction())
513+
or
514+
// Instruction -> Operand flow
515+
simpleOperandLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asOperand())
516516
}
517517

518518
pragma[noinline]
@@ -524,26 +524,21 @@ private predicate getFieldSizeOfClass(Class c, Type type, int size) {
524524
)
525525
}
526526

527-
private predicate simpleOperandLocalFlowStep(Operand opFrom, Instruction iTo) {
528-
// Certain dataflow steps (for instance `PostUpdateNode.getPreUpdateNode()`) generates flow to
529-
// operands, so we include dataflow from those operands to the "result" of the instruction (i.e., to
530-
// the instruction itself).
531-
exists(PostUpdateNode post |
532-
opFrom = post.getPreUpdateNode().asOperand() and
533-
iTo.getAnOperand() = opFrom
534-
)
527+
cached
528+
private predicate simpleOperandLocalFlowStep(Instruction iFrom, Operand opTo) {
529+
opTo.getAnyDef() = iFrom
535530
}
536531

537532
cached
538-
private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction iTo) {
539-
iTo.(CopyInstruction).getSourceValue() = iFrom
533+
private predicate simpleInstructionLocalFlowStep(Operand opFrom, Instruction iTo) {
534+
iTo.(CopyInstruction).getSourceValueOperand() = opFrom and not opFrom.isDefinitionInexact()
540535
or
541-
iTo.(PhiInstruction).getAnOperand().getDef() = iFrom
536+
iTo.(PhiInstruction).getAnInputOperand() = opFrom and not opFrom.isDefinitionInexact()
542537
or
543538
// A read side effect is almost never exact since we don't know exactly how
544539
// much memory the callee will read.
545-
iTo.(ReadSideEffectInstruction).getSideEffectOperand().getAnyDef() = iFrom and
546-
not iFrom.isResultConflated()
540+
iTo.(ReadSideEffectInstruction).getSideEffectOperand() = opFrom and
541+
not opFrom.getAnyDef().isResultConflated()
547542
or
548543
// Loading a single `int` from an `int *` parameter is not an exact load since
549544
// the parameter may point to an entire array rather than a single `int`. The
@@ -556,8 +551,8 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction
556551
// reassignment of the parameter indirection, including a conditional one that
557552
// leads to a phi node.
558553
exists(InitializeIndirectionInstruction init |
559-
iFrom = init and
560-
iTo.(LoadInstruction).getSourceValueOperand().getAnyDef() = init and
554+
opFrom.getAnyDef() = init and
555+
iTo.(LoadInstruction).getSourceValueOperand() = opFrom and
561556
// Check that the types match. Otherwise we can get flow from an object to
562557
// its fields, which leads to field conflation when there's flow from other
563558
// fields to the object elsewhere.
@@ -566,11 +561,13 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction
566561
)
567562
or
568563
// Treat all conversions as flow, even conversions between different numeric types.
569-
iTo.(ConvertInstruction).getUnary() = iFrom
564+
iTo.(ConvertInstruction).getUnaryOperand() = opFrom and not opFrom.isDefinitionInexact()
570565
or
571-
iTo.(CheckedConvertOrNullInstruction).getUnary() = iFrom
566+
iTo.(CheckedConvertOrNullInstruction).getUnaryOperand() = opFrom and
567+
not opFrom.isDefinitionInexact()
572568
or
573-
iTo.(InheritanceConversionInstruction).getUnary() = iFrom
569+
iTo.(InheritanceConversionInstruction).getUnaryOperand() = opFrom and
570+
not opFrom.isDefinitionInexact()
574571
or
575572
// A chi instruction represents a point where a new value (the _partial_
576573
// operand) may overwrite an old value (the _total_ operand), but the alias
@@ -583,7 +580,7 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction
583580
//
584581
// Flow through the partial operand belongs in the taint-tracking libraries
585582
// for now.
586-
iTo.getAnOperand().(ChiTotalOperand).getDef() = iFrom
583+
iTo.getAnOperand().(ChiTotalOperand) = opFrom
587584
or
588585
// Add flow from write side-effects to non-conflated chi instructions through their
589586
// partial operands. From there, a `readStep` will find subsequent reads of that field.
@@ -598,24 +595,25 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction
598595
// Here, a `WriteSideEffectInstruction` will provide a new definition for `p->x` after the call to
599596
// `setX`, which will be melded into `p` through a chi instruction.
600597
exists(ChiInstruction chi | chi = iTo |
601-
chi.getPartialOperand().getDef() = iFrom.(WriteSideEffectInstruction) and
598+
opFrom.getAnyDef() instanceof WriteSideEffectInstruction and
599+
chi.getPartialOperand() = opFrom and
602600
not chi.isResultConflated()
603601
)
604602
or
605603
// Flow from stores to structs with a single field to a load of that field.
606-
iTo.(LoadInstruction).getSourceValueOperand().getAnyDef() = iFrom and
604+
iTo.(LoadInstruction).getSourceValueOperand() = opFrom and
607605
exists(int size, Type type, Class cTo |
608-
type = iFrom.getResultType() and
606+
type = opFrom.getAnyDef().getResultType() and
609607
cTo = iTo.getResultType() and
610608
cTo.getSize() = size and
611609
getFieldSizeOfClass(cTo, type, size)
612610
)
613611
or
614612
// Flow through modeled functions
615-
modelFlow(iFrom, iTo)
613+
modelFlow(opFrom, iTo)
616614
}
617615

618-
private predicate modelFlow(Instruction iFrom, Instruction iTo) {
616+
private predicate modelFlow(Operand opFrom, Instruction iTo) {
619617
exists(
620618
CallInstruction call, DataFlowFunction func, FunctionInput modelIn, FunctionOutput modelOut
621619
|
@@ -640,17 +638,17 @@ private predicate modelFlow(Instruction iFrom, Instruction iTo) {
640638
(
641639
exists(int index |
642640
modelIn.isParameter(index) and
643-
iFrom = call.getPositionalArgument(index)
641+
opFrom = call.getPositionalArgumentOperand(index)
644642
)
645643
or
646644
exists(int index, ReadSideEffectInstruction read |
647645
modelIn.isParameterDeref(index) and
648646
read = getSideEffectFor(call, index) and
649-
iFrom = read.getSideEffectOperand().getAnyDef()
647+
opFrom = read.getSideEffectOperand()
650648
)
651649
or
652650
modelIn.isQualifierAddress() and
653-
iFrom = call.getThisArgument()
651+
opFrom = call.getThisArgumentOperand()
654652
// TODO: add read side effects for qualifiers
655653
)
656654
)

0 commit comments

Comments
 (0)