Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a36453b

Browse files
committed
Python taint-tracking. Fix performance for a couple of predicates.
1 parent 76c11c4 commit a36453b

1 file changed

Lines changed: 46 additions & 24 deletions

File tree

python/ql/src/semmle/python/dataflow/Implementation.qll

Lines changed: 46 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -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 */
797813
private 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+
803825
module Implementation {
804826

805827
/* A call that returns a copy (or similar) of the argument */

0 commit comments

Comments
 (0)