@@ -684,19 +684,35 @@ private class EssaTaintTracking extends string {
684684 )
685685 }
686686
687- pragma [ noinline]
688687 private predicate taintedPiNode ( TaintTrackingNode src , PyEdgeRefinement defn , TaintTrackingContext context , AttributePath path , TaintKind kind ) {
689- exists ( DataFlow:: Node srcnode |
688+ taintedPiNodeOneway ( src , defn , context , path , kind )
689+ or
690+ taintedPiNodeBothways ( src , defn , context , path , kind )
691+ }
692+
693+ pragma [ noinline]
694+ private predicate taintedPiNodeOneway ( TaintTrackingNode src , PyEdgeRefinement defn , TaintTrackingContext context , AttributePath path , TaintKind kind ) {
695+ exists ( DataFlow:: Node srcnode , ControlFlowNode test , ControlFlowNode use |
690696 src = TTaintTrackingNode_ ( srcnode , context , path , kind , this ) and
697+ piNodeTestAndUse ( defn , test , use ) and
691698 srcnode .asVariable ( ) = defn .getInput ( ) and
692- not this .( TaintTracking:: Configuration ) .isBarrierTest ( defn .getTest ( ) , defn .getSense ( ) )
693- |
694- defn .getSense ( ) = testEvaluates ( defn .getTest ( ) , defn .getInput ( ) .getSourceVariable ( ) .getAUse ( ) , kind )
695- or
696- testEvaluatesMaybe ( defn .getTest ( ) , defn .getInput ( ) .getSourceVariable ( ) .getAUse ( ) )
699+ not this .( TaintTracking:: Configuration ) .isBarrierTest ( test , defn .getSense ( ) ) and
700+ defn .getSense ( ) = testEvaluates ( test , use , kind )
701+ )
702+ }
703+
704+ pragma [ noinline]
705+ private predicate taintedPiNodeBothways ( TaintTrackingNode src , PyEdgeRefinement defn , TaintTrackingContext context , AttributePath path , TaintKind kind ) {
706+ exists ( DataFlow:: Node srcnode , ControlFlowNode test , ControlFlowNode use |
707+ src = TTaintTrackingNode_ ( srcnode , context , path , kind , this ) and
708+ piNodeTestAndUse ( defn , test , use ) and
709+ srcnode .asVariable ( ) = defn .getInput ( ) and
710+ not this .( TaintTracking:: Configuration ) .isBarrierTest ( test , defn .getSense ( ) ) and
711+ testEvaluatesMaybe ( test , use )
697712 )
698713 }
699714
715+
700716 pragma [ noinline]
701717 private predicate taintedArgument ( TaintTrackingNode src , ArgumentRefinement defn , TaintTrackingContext context , AttributePath path , TaintKind kind ) {
702718 exists ( DataFlow:: Node srcnode |
@@ -759,23 +775,6 @@ private class EssaTaintTracking extends string {
759775 )
760776 }
761777
762- private predicate testEvaluatesMaybe ( ControlFlowNode test , ControlFlowNode use ) {
763- any ( PyEdgeRefinement ref ) .getTest ( ) .getAChild * ( ) = test and
764- test .getAChild * ( ) = use and
765- not test .( UnaryExprNode ) .getNode ( ) .getOp ( ) instanceof Not and
766- not Filters:: equality_test ( test , use , _, _) and
767- not Filters:: isinstance ( test , _, use ) and
768- not test = use
769- or
770- testEvaluatesMaybe ( not_operand ( test ) , use )
771- }
772-
773- /** Gets the operand of a unary `not` expression. */
774- private ControlFlowNode not_operand ( ControlFlowNode expr ) {
775- expr .( UnaryExprNode ) .getNode ( ) .getOp ( ) instanceof Not and
776- result = expr .( UnaryExprNode ) .getOperand ( )
777- }
778-
779778 /** Holds if `test` is the test in a branch and `use` is that test
780779 * with all the `not` prefixes removed.
781780 */
@@ -793,13 +792,36 @@ private class EssaTaintTracking extends string {
793792
794793}
795794
795+ private predicate testEvaluatesMaybe ( ControlFlowNode test , ControlFlowNode use ) {
796+ any ( PyEdgeRefinement ref ) .getTest ( ) .getAChild * ( ) = test and
797+ test .getAChild * ( ) = use and
798+ not test .( UnaryExprNode ) .getNode ( ) .getOp ( ) instanceof Not and
799+ not Filters:: equality_test ( test , use , _, _) and
800+ not Filters:: isinstance ( test , _, use ) and
801+ not test = use
802+ or
803+ testEvaluatesMaybe ( not_operand ( test ) , use )
804+ }
805+
806+ /** Gets the operand of a unary `not` expression. */
807+ private ControlFlowNode not_operand ( ControlFlowNode expr ) {
808+ expr .( UnaryExprNode ) .getNode ( ) .getOp ( ) instanceof Not and
809+ result = expr .( UnaryExprNode ) .getOperand ( )
810+ }
811+
796812/* Helper predicate for tainted_with */
797813private predicate with_flow ( With with , ControlFlowNode contextManager , ControlFlowNode var ) {
798814 with .getContextExpr ( ) = contextManager .getNode ( ) and
799815 with .getOptionalVars ( ) = var .getNode ( ) and
800816 contextManager .strictlyDominates ( var )
801817}
802818
819+ /* Helper predicate for taintedPiNode */
820+ pragma [ noinline]
821+ private predicate piNodeTestAndUse ( PyEdgeRefinement defn , ControlFlowNode test , ControlFlowNode use ) {
822+ test = defn .getTest ( ) and use = defn .getInput ( ) .getASourceUse ( ) and test .getAChild * ( ) = use
823+ }
824+
803825module Implementation {
804826
805827 /* A call that returns a copy (or similar) of the argument */
0 commit comments