Skip to content

Commit 8bb1d86

Browse files
committed
Python: Add call-graph hotfix for sympy
1 parent 23144f5 commit 8bb1d86

File tree

1 file changed

+30
-0
lines changed

1 file changed

+30
-0
lines changed

python/ql/lib/semmle/python/dataflow/new/internal/DataFlowDispatch.qll

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,10 +460,26 @@ private CallCfgNode getSuperCall() {
460460
)
461461
}
462462

463+
/**
464+
* Holds if the file `f` should be ignored when computing the call-graph.
465+
*
466+
* We currently see a performance problem when analyzing the `sympy` PyPI package,
467+
* which can be part of the database when dependencies are installed and extracted.
468+
* From what we can understand, SymPy is using Python in a exotic way, so the fact that
469+
* our analysis currently does not handle this project has nothing to say about our
470+
* ability to handle normal Python code. Furthermore, SymPy does not look to be relevant
471+
* in a security context, so we should not loose out on any security results by doing
472+
* this.
473+
*/
474+
private predicate ignoreForCallGraph(File f) {
475+
f.getAbsolutePath().matches("%/site-packages/sympy/%")
476+
}
477+
463478
/**
464479
* Gets a reference to the function `func`.
465480
*/
466481
private TypeTrackingNode functionTracker(TypeTracker t, Function func) {
482+
not ignoreForCallGraph(result.getLocation().getFile()) and
467483
t.start() and
468484
(
469485
result.asExpr() = func.getDefinition()
@@ -473,6 +489,7 @@ private TypeTrackingNode functionTracker(TypeTracker t, Function func) {
473489
result.asExpr() = func.getDefinition().(FunctionExpr).getADecoratorCall()
474490
)
475491
or
492+
not ignoreForCallGraph(result.getLocation().getFile()) and
476493
exists(TypeTracker t2 | result = functionTracker(t2, func).track(t2, t))
477494
}
478495

@@ -485,6 +502,7 @@ Node functionTracker(Function func) { functionTracker(TypeTracker::end(), func).
485502
* Gets a reference to the class `cls`.
486503
*/
487504
private TypeTrackingNode classTracker(TypeTracker t, Class cls) {
505+
not ignoreForCallGraph(result.getLocation().getFile()) and
488506
t.start() and
489507
(
490508
result.asExpr() = cls.getParent()
@@ -498,6 +516,7 @@ private TypeTrackingNode classTracker(TypeTracker t, Class cls) {
498516
result.(CallCfgNode).getArg(0) = classInstanceTracker(cls)
499517
)
500518
or
519+
not ignoreForCallGraph(result.getLocation().getFile()) and
501520
exists(TypeTracker t2 | result = classTracker(t2, cls).track(t2, t)) and
502521
not result.(ParameterNodeImpl).isParameterOf(_, any(ParameterPosition pp | pp.isSelf()))
503522
}
@@ -511,16 +530,19 @@ Node classTracker(Class cls) { classTracker(TypeTracker::end(), cls).flowsTo(res
511530
* Gets a reference to an instance of the class `cls`.
512531
*/
513532
private TypeTrackingNode classInstanceTracker(TypeTracker t, Class cls) {
533+
not ignoreForCallGraph(result.getLocation().getFile()) and
514534
t.start() and
515535
resolveClassCall(result.(CallCfgNode).asCfgNode(), cls)
516536
or
517537
// result of `super().__new__` as used in a `__new__` method implementation
538+
not ignoreForCallGraph(result.getLocation().getFile()) and
518539
t.start() and
519540
exists(Class classUsedInSuper |
520541
fromSuperNewCall(result.(CallCfgNode).asCfgNode(), classUsedInSuper, _, _) and
521542
classUsedInSuper = getADirectSuperclass*(cls)
522543
)
523544
or
545+
not ignoreForCallGraph(result.getLocation().getFile()) and
524546
exists(TypeTracker t2 | result = classInstanceTracker(t2, cls).track(t2, t)) and
525547
not result.(ParameterNodeImpl).isParameterOf(_, any(ParameterPosition pp | pp.isSelf()))
526548
}
@@ -537,6 +559,7 @@ Node classInstanceTracker(Class cls) {
537559
* The method cannot be a `staticmethod` or `classmethod`.
538560
*/
539561
private TypeTrackingNode selfTracker(TypeTracker t, Class classWithMethod) {
562+
not ignoreForCallGraph(result.getLocation().getFile()) and
540563
t.start() and
541564
exists(Function func |
542565
func = classWithMethod.getAMethod() and
@@ -546,6 +569,7 @@ private TypeTrackingNode selfTracker(TypeTracker t, Class classWithMethod) {
546569
result.asExpr() = func.getArg(0)
547570
)
548571
or
572+
not ignoreForCallGraph(result.getLocation().getFile()) and
549573
exists(TypeTracker t2 | result = selfTracker(t2, classWithMethod).track(t2, t)) and
550574
not result.(ParameterNodeImpl).isParameterOf(_, any(ParameterPosition pp | pp.isSelf()))
551575
}
@@ -564,6 +588,7 @@ Node selfTracker(Class classWithMethod) {
564588
* from a normal method.
565589
*/
566590
private TypeTrackingNode clsArgumentTracker(TypeTracker t, Class classWithMethod) {
591+
not ignoreForCallGraph(result.getLocation().getFile()) and
567592
t.start() and
568593
(
569594
exists(Function func |
@@ -578,6 +603,7 @@ private TypeTrackingNode clsArgumentTracker(TypeTracker t, Class classWithMethod
578603
result.(CallCfgNode).getArg(0) = selfTracker(classWithMethod)
579604
)
580605
or
606+
not ignoreForCallGraph(result.getLocation().getFile()) and
581607
exists(TypeTracker t2 | result = clsArgumentTracker(t2, classWithMethod).track(t2, t)) and
582608
not result.(ParameterNodeImpl).isParameterOf(_, any(ParameterPosition pp | pp.isSelf()))
583609
}
@@ -596,6 +622,7 @@ Node clsArgumentTracker(Class classWithMethod) {
596622
* call happened in the method `func` (either a method or a classmethod).
597623
*/
598624
private TypeTrackingNode superCallNoArgumentTracker(TypeTracker t, Function func) {
625+
not ignoreForCallGraph(result.getLocation().getFile()) and
599626
t.start() and
600627
not isStaticmethod(func) and
601628
exists(CallCfgNode call | result = call |
@@ -604,6 +631,7 @@ private TypeTrackingNode superCallNoArgumentTracker(TypeTracker t, Function func
604631
call.getScope() = func
605632
)
606633
or
634+
not ignoreForCallGraph(result.getLocation().getFile()) and
607635
exists(TypeTracker t2 | result = superCallNoArgumentTracker(t2, func).track(t2, t)) and
608636
not result.(ParameterNodeImpl).isParameterOf(_, any(ParameterPosition pp | pp.isSelf()))
609637
}
@@ -621,13 +649,15 @@ Node superCallNoArgumentTracker(Function func) {
621649
* first is a reference to the class `cls`, and the second argument is `obj`.
622650
*/
623651
private TypeTrackingNode superCallTwoArgumentTracker(TypeTracker t, Class cls, Node obj) {
652+
not ignoreForCallGraph(result.getLocation().getFile()) and
624653
t.start() and
625654
exists(CallCfgNode call | result = call |
626655
call = getSuperCall() and
627656
call.getArg(0) = classTracker(cls) and
628657
call.getArg(1) = obj
629658
)
630659
or
660+
not ignoreForCallGraph(result.getLocation().getFile()) and
631661
exists(TypeTracker t2 | result = superCallTwoArgumentTracker(t2, cls, obj).track(t2, t)) and
632662
not result.(ParameterNodeImpl).isParameterOf(_, any(ParameterPosition pp | pp.isSelf()))
633663
}

0 commit comments

Comments
 (0)