@@ -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 */
510510predicate 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
518518pragma [ 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
537532cached
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