@@ -332,6 +332,10 @@ private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
332
332
)
333
333
}
334
334
335
+ // By using an operand as the result of this predicate we avoid the dataflow inconsistency errors
336
+ // caused by having multiple nodes sharing the same pre update node. This inconsistency error can cause
337
+ // a tuple explosion in the big step dataflow relation since it can make many nodes be the entry node
338
+ // into a big step.
335
339
override Node getPreUpdateNode ( ) { result .asOperand ( ) = instr .getTotalOperand ( ) }
336
340
337
341
override Expr getDefinedExpr ( ) {
@@ -504,10 +508,11 @@ predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFr
504
508
* data flow. It may have less flow than the `localFlowStep` predicate.
505
509
*/
506
510
predicate simpleLocalFlowStep ( Node nodeFrom , Node nodeTo ) {
507
- simpleInstructionLocalFlowStep ( nodeFrom .asOperand ( ) , nodeTo .asInstruction ( ) )
511
+ // Instruction -> Instruction flow
512
+ simpleInstructionLocalFlowStep ( nodeFrom .asInstruction ( ) , nodeTo .asInstruction ( ) )
508
513
or
509
- // Flow from an instruction to its operands
510
- nodeTo .asOperand ( ) . getAnyDef ( ) = nodeFrom .asInstruction ( )
514
+ // Operand -> Instruction flow
515
+ simpleOperandLocalFlowStep ( nodeFrom .asOperand ( ) , nodeTo .asInstruction ( ) )
511
516
}
512
517
513
518
pragma [ noinline]
@@ -519,16 +524,26 @@ private predicate getFieldSizeOfClass(Class c, Type type, int size) {
519
524
)
520
525
}
521
526
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
+ )
535
+ }
536
+
522
537
cached
523
- private predicate simpleInstructionLocalFlowStep ( Operand opFrom , Instruction iTo ) {
524
- iTo .( CopyInstruction ) .getSourceValueOperand ( ) = opFrom and not opFrom . isDefinitionInexact ( )
538
+ private predicate simpleInstructionLocalFlowStep ( Instruction iFrom , Instruction iTo ) {
539
+ iTo .( CopyInstruction ) .getSourceValue ( ) = iFrom
525
540
or
526
- iTo .( PhiInstruction ) .getAnInputOperand ( ) = opFrom and not opFrom . isDefinitionInexact ( )
541
+ iTo .( PhiInstruction ) .getAnOperand ( ) . getDef ( ) = iFrom
527
542
or
528
543
// A read side effect is almost never exact since we don't know exactly how
529
544
// much memory the callee will read.
530
- iTo .( ReadSideEffectInstruction ) .getSideEffectOperand ( ) = opFrom and
531
- not opFrom . getAnyDef ( ) .isResultConflated ( )
545
+ iTo .( ReadSideEffectInstruction ) .getSideEffectOperand ( ) . getAnyDef ( ) = iFrom and
546
+ not iFrom .isResultConflated ( )
532
547
or
533
548
// Loading a single `int` from an `int *` parameter is not an exact load since
534
549
// the parameter may point to an entire array rather than a single `int`. The
@@ -541,8 +556,8 @@ private predicate simpleInstructionLocalFlowStep(Operand opFrom, Instruction iTo
541
556
// reassignment of the parameter indirection, including a conditional one that
542
557
// leads to a phi node.
543
558
exists ( InitializeIndirectionInstruction init |
544
- opFrom . getAnyDef ( ) = init and
545
- iTo .( LoadInstruction ) .getSourceValueOperand ( ) = opFrom and
559
+ iFrom = init and
560
+ iTo .( LoadInstruction ) .getSourceValueOperand ( ) . getAnyDef ( ) = init and
546
561
// Check that the types match. Otherwise we can get flow from an object to
547
562
// its fields, which leads to field conflation when there's flow from other
548
563
// fields to the object elsewhere.
@@ -551,13 +566,11 @@ private predicate simpleInstructionLocalFlowStep(Operand opFrom, Instruction iTo
551
566
)
552
567
or
553
568
// Treat all conversions as flow, even conversions between different numeric types.
554
- iTo .( ConvertInstruction ) .getUnaryOperand ( ) = opFrom and not opFrom . isDefinitionInexact ( )
569
+ iTo .( ConvertInstruction ) .getUnary ( ) = iFrom
555
570
or
556
- iTo .( CheckedConvertOrNullInstruction ) .getUnaryOperand ( ) = opFrom and
557
- not opFrom .isDefinitionInexact ( )
571
+ iTo .( CheckedConvertOrNullInstruction ) .getUnary ( ) = iFrom
558
572
or
559
- iTo .( InheritanceConversionInstruction ) .getUnaryOperand ( ) = opFrom and
560
- not opFrom .isDefinitionInexact ( )
573
+ iTo .( InheritanceConversionInstruction ) .getUnary ( ) = iFrom
561
574
or
562
575
// A chi instruction represents a point where a new value (the _partial_
563
576
// operand) may overwrite an old value (the _total_ operand), but the alias
@@ -570,7 +583,7 @@ private predicate simpleInstructionLocalFlowStep(Operand opFrom, Instruction iTo
570
583
//
571
584
// Flow through the partial operand belongs in the taint-tracking libraries
572
585
// for now.
573
- iTo .getAnOperand ( ) .( ChiTotalOperand ) = opFrom
586
+ iTo .getAnOperand ( ) .( ChiTotalOperand ) . getDef ( ) = iFrom
574
587
or
575
588
// Add flow from write side-effects to non-conflated chi instructions through their
576
589
// partial operands. From there, a `readStep` will find subsequent reads of that field.
@@ -585,25 +598,24 @@ private predicate simpleInstructionLocalFlowStep(Operand opFrom, Instruction iTo
585
598
// Here, a `WriteSideEffectInstruction` will provide a new definition for `p->x` after the call to
586
599
// `setX`, which will be melded into `p` through a chi instruction.
587
600
exists ( ChiInstruction chi | chi = iTo |
588
- opFrom .getAnyDef ( ) instanceof WriteSideEffectInstruction and
589
- chi .getPartialOperand ( ) = opFrom and
601
+ chi .getPartialOperand ( ) .getDef ( ) = iFrom .( WriteSideEffectInstruction ) and
590
602
not chi .isResultConflated ( )
591
603
)
592
604
or
593
605
// Flow from stores to structs with a single field to a load of that field.
594
- iTo .( LoadInstruction ) .getSourceValueOperand ( ) = opFrom and
606
+ iTo .( LoadInstruction ) .getSourceValueOperand ( ) . getAnyDef ( ) = iFrom and
595
607
exists ( int size , Type type , Class cTo |
596
- type = opFrom . getAnyDef ( ) .getResultType ( ) and
608
+ type = iFrom .getResultType ( ) and
597
609
cTo = iTo .getResultType ( ) and
598
610
cTo .getSize ( ) = size and
599
611
getFieldSizeOfClass ( cTo , type , size )
600
612
)
601
613
or
602
614
// Flow through modeled functions
603
- modelFlow ( opFrom , iTo )
615
+ modelFlow ( iFrom , iTo )
604
616
}
605
617
606
- private predicate modelFlow ( Operand opFrom , Instruction iTo ) {
618
+ private predicate modelFlow ( Instruction iFrom , Instruction iTo ) {
607
619
exists (
608
620
CallInstruction call , DataFlowFunction func , FunctionInput modelIn , FunctionOutput modelOut
609
621
|
@@ -628,17 +640,17 @@ private predicate modelFlow(Operand opFrom, Instruction iTo) {
628
640
(
629
641
exists ( int index |
630
642
modelIn .isParameter ( index ) and
631
- opFrom = call .getPositionalArgumentOperand ( index )
643
+ iFrom = call .getPositionalArgument ( index )
632
644
)
633
645
or
634
646
exists ( int index , ReadSideEffectInstruction read |
635
647
modelIn .isParameterDeref ( index ) and
636
648
read = getSideEffectFor ( call , index ) and
637
- opFrom = read .getSideEffectOperand ( )
649
+ iFrom = read .getSideEffectOperand ( ) . getAnyDef ( )
638
650
)
639
651
or
640
652
modelIn .isQualifierAddress ( ) and
641
- opFrom = call .getThisArgumentOperand ( )
653
+ iFrom = call .getThisArgument ( )
642
654
// TODO: add read side effects for qualifiers
643
655
)
644
656
)
0 commit comments