@@ -1237,7 +1237,7 @@ library module TaintFlowImplementation {
12371237 )
12381238 |
12391239 not Filters:: isinstance ( test .getTest ( ) , _, var .getSourceVariable ( ) .getAUse ( ) ) and
1240- not test .getTest ( ) = var .getSourceVariable ( ) .getAUse ( )
1240+ not boolean_filter ( test .getTest ( ) , var .getSourceVariable ( ) .getAUse ( ) )
12411241 or
12421242 exists ( ControlFlowNode c , ClassObject cls |
12431243 Filters:: isinstance ( test .getTest ( ) , c , var .getSourceVariable ( ) .getAUse ( ) )
@@ -1248,10 +1248,42 @@ library module TaintFlowImplementation {
12481248 test .getSense ( ) = false and not kind .getClass ( ) .getAnImproperSuperType ( ) = cls
12491249 )
12501250 or
1251- test .getTest ( ) = var .getSourceVariable ( ) .getAUse ( ) and kind . booleanValue ( ) = test . getSense ( )
1251+ test .getSense ( ) = test_evaluates ( test . getTest ( ) , var .getSourceVariable ( ) .getAUse ( ) , kind )
12521252 )
12531253 }
12541254
1255+ /** Gets the operand of a unary `not` expression. */
1256+ private ControlFlowNode not_operand ( ControlFlowNode expr ) {
1257+ expr .( UnaryExprNode ) .getNode ( ) .getOp ( ) instanceof Not and
1258+ result = expr .( UnaryExprNode ) .getOperand ( )
1259+ }
1260+
1261+ /** Holds if `test` is the test in a branch and `use` is that test
1262+ * with all the `not` prefixes removed.
1263+ */
1264+ private predicate boolean_filter ( ControlFlowNode test , ControlFlowNode use ) {
1265+ any ( PyEdgeRefinement ref ) .getTest ( ) = test and
1266+ (
1267+ use = test
1268+ or
1269+ exists ( ControlFlowNode notuse |
1270+ boolean_filter ( test , notuse ) and
1271+ use = not_operand ( notuse )
1272+ )
1273+ )
1274+ }
1275+
1276+ /** Gets the boolean value that `test` evaluates to when `use` is tainted with `kind`
1277+ * and `test` and `use` are part of a test in a branch.
1278+ */
1279+ private boolean test_evaluates ( ControlFlowNode test , ControlFlowNode use , TaintKind kind ) {
1280+ boolean_filter ( _, use ) and
1281+ kind .taints ( use ) and
1282+ test = use and result = kind .booleanValue ( )
1283+ or
1284+ result = test_evaluates ( not_operand ( test ) , use , kind ) .booleanNot ( )
1285+ }
1286+
12551287 pragma [ noinline]
12561288 predicate tainted_argument ( ArgumentRefinement def , CallContext context , TaintedNode origin ) {
12571289 tainted_var ( def .getInput ( ) , context , origin )
0 commit comments