@@ -36,22 +36,34 @@ class MySanitizerHandlingNot extends Sanitizer {
3636 /** The test `if is_safe(arg):` sanitizes `arg` on its `true` edge. */
3737 override predicate sanitizingEdge ( TaintKind taint , PyEdgeRefinement test ) {
3838 taint instanceof ExternalStringKind and
39- exists ( CallNode call |
40- clears_taint_on_true ( call , test .getTest ( ) , test .getSense ( ) )
41- |
42- call = Value:: named ( "test.is_safe" ) .getACall ( ) and
43- test .getInput ( ) .getAUse ( ) = call .getAnArg ( )
44- )
39+ clears_taint_on_true ( _, test .getTest ( ) , test .getSense ( ) , test )
4540 }
4641
47- private predicate clears_taint_on_true ( ControlFlowNode final_test , ControlFlowNode test , boolean sense ) {
48- final_test = test and
49- sense = true
50- or
51- test .( UnaryExprNode ) .getNode ( ) .getOp ( ) instanceof Not and
52- exists ( ControlFlowNode nested_test |
53- nested_test = test .( UnaryExprNode ) .getOperand ( ) and
54- clears_taint_on_true ( final_test , nested_test , sense .booleanNot ( ) )
42+ /**
43+ * Helper predicate that recurses into any nesting of `not`
44+ *
45+ * To reduce the number of tuples this predicate holds for, we include the `PyEdgeRefinement` and
46+ * ensure that `test` is a part of this `PyEdgeRefinement`. Without including `PyEdgeRefinement` as an argument
47+ * *any* `CallNode c` to `test.is_safe` would be a result of this predicate, since (c, c, true) would hold.
48+ */
49+ private predicate clears_taint_on_true (
50+ CallNode final_test , ControlFlowNode test , boolean sense , PyEdgeRefinement edge_refinement
51+ ) {
52+ (
53+ edge_refinement .getTest ( ) .getNode ( ) .( Expr ) .getASubExpression * ( ) = test .getNode ( ) and
54+ test .getNode ( ) .( Expr ) .getASubExpression * ( ) = final_test .getNode ( )
55+ ) and
56+ (
57+ final_test = test and
58+ final_test = Value:: named ( "test.is_safe" ) .getACall ( ) and
59+ edge_refinement .getInput ( ) .getAUse ( ) = final_test .getAnArg ( ) and
60+ sense = true
61+ or
62+ test .( UnaryExprNode ) .getNode ( ) .getOp ( ) instanceof Not and
63+ exists ( ControlFlowNode nested_test |
64+ nested_test = test .( UnaryExprNode ) .getOperand ( ) and
65+ clears_taint_on_true ( final_test , nested_test , sense .booleanNot ( ) , edge_refinement )
66+ )
5567 )
5668 }
5769}
0 commit comments