Skip to content

Commit e77c105

Browse files
committed
Python: Use source nodes and prevent bad join order
1 parent cac6c4a commit e77c105

File tree

1 file changed

+19
-6
lines changed

1 file changed

+19
-6
lines changed

python/ql/src/semmle/python/regex.qll

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,27 +71,40 @@ private string canonical_name(API::Node flag) {
7171
* A type tracker for regular expression flag names. Holds if the result is a node that may refer
7272
* to the `re` flag with the canonical name `flag_name`
7373
*/
74-
private DataFlow::Node re_flag_tracker(string flag_name, DataFlow::TypeTracker t) {
74+
private DataFlow::LocalSourceNode re_flag_tracker(string flag_name, DataFlow::TypeTracker t) {
7575
t.start() and
7676
exists(API::Node flag | flag_name = canonical_name(flag) and result = flag.getAUse())
7777
or
78-
exists(BinaryExprNode binop |
78+
exists(BinaryExprNode binop, DataFlow::Node operand |
79+
operand.getALocalSource() = re_flag_tracker(flag_name, t.continue()) and
80+
operand.asCfgNode() = binop.getAnOperand() and
7981
(binop.getOp() instanceof BitOr or binop.getOp() instanceof Add) and
80-
binop.getAnOperand() = re_flag_tracker(flag_name, t.continue()).asCfgNode() and
8182
result.asCfgNode() = binop
8283
)
8384
or
84-
exists(DataFlow::TypeTracker t2, DataFlow::Node prev | prev = re_flag_tracker(flag_name, t2) |
85-
t2 = t.smallstep(prev, result)
85+
// Due to bad performance when using normal setup with `re_flag_tracker(t2, attr_name).track(t2, t)`
86+
// we have inlined that code and forced a join
87+
exists(DataFlow::TypeTracker t2 |
88+
exists(DataFlow::StepSummary summary |
89+
re_flag_tracker_first_join(t2, flag_name, result, summary) and
90+
t = t2.append(summary)
91+
)
8692
)
8793
}
8894

95+
pragma[nomagic]
96+
private predicate re_flag_tracker_first_join(
97+
DataFlow::TypeTracker t2, string flag_name, DataFlow::Node res, DataFlow::StepSummary summary
98+
) {
99+
DataFlow::StepSummary::step(re_flag_tracker(flag_name, t2), res, summary)
100+
}
101+
89102
/**
90103
* A type tracker for regular expression flag names. Holds if the result is a node that may refer
91104
* to the `re` flag with the canonical name `flag_name`
92105
*/
93106
private DataFlow::Node re_flag_tracker(string flag_name) {
94-
result = re_flag_tracker(flag_name, DataFlow::TypeTracker::end())
107+
re_flag_tracker(flag_name, DataFlow::TypeTracker::end()).flowsTo(result)
95108
}
96109

97110
/** Gets a regular expression mode flag associated with the given data flow node. */

0 commit comments

Comments
 (0)