1313import java
1414import semmle.code.java.dataflow.DataFlow
1515
16-
1716predicate isTestPackage ( RefType referenceType ) {
1817 referenceType .getPackage ( ) .getName ( ) .toLowerCase ( ) .matches ( "%test%" ) or
1918 referenceType .getPackage ( ) .getName ( ) .toLowerCase ( ) .matches ( "%benchmark%" ) or
@@ -24,11 +23,25 @@ class RecursionSource extends MethodCall {
2423 RecursionSource ( ) { not isTestPackage ( this .getCaller ( ) .getDeclaringType ( ) ) }
2524
2625 override string toString ( ) {
27- result = this .getCaller ( ) .toString ( ) + " calls " + this .getCallee ( ) .toString ( )
26+ result = this .getCaller ( ) .toString ( ) + " clls " + this .getCallee ( ) .toString ( )
2827 }
2928
3029}
3130
31+ /**
32+ * Check if the Expr uses directly an argument of the enclosing function
33+ */
34+ class ParameterOperation extends Expr {
35+ ParameterOperation ( ) {
36+ this instanceof BinaryExpr or this instanceof UnaryAssignExpr
37+ and exists (
38+ VarAccess va |
39+ va .getVariable ( ) = this .getEnclosingCallable ( ) .getAParameter ( ) |
40+ this .getAChildExpr + ( ) = va
41+ )
42+ }
43+ }
44+
3245module RecursiveConfig implements DataFlow:: StateConfigSig {
3346 class FlowState = Method ;
3447
@@ -44,12 +57,26 @@ module RecursiveConfig implements DataFlow::StateConfigSig {
4457 }
4558
4659 predicate isBarrier ( DataFlow:: Node node ) {
47- node .asExpr ( ) instanceof MethodCall and
48- exists ( Expr arg | arg = node .asExpr ( ) .( MethodCall ) .getAnArgument ( ) |
49- arg instanceof BinaryExpr or
50- exists ( BinaryExpr b | DataFlow:: localFlow ( DataFlow:: exprNode ( b ) , DataFlow:: exprNode ( arg ) ) )
60+ exists ( MethodCall ma |
61+ ma = node .asExpr ( )
62+ and (
63+ exists ( Expr e | e = ma .getAnArgument ( ) and e instanceof ParameterOperation )
64+ // or exists(
65+ // VarAccess e|
66+ // e = ma.getAnArgument() |
67+ // e.getVariable().getAnAssignedValue().getAChildExpr() instanceof ParameterOperation
68+ // )
69+ )
5170 )
5271 }
72+
73+ /**
74+ * Weird but useful deduplication logic
75+ */
76+ predicate isBarrierIn ( DataFlow:: Node node , FlowState state ) {
77+ not node .asExpr ( ) instanceof MethodCall
78+ or node .asExpr ( ) .( MethodCall ) .getCaller ( ) .getLocation ( ) .getStartLine ( ) > state .getLocation ( ) .getStartLine ( )
79+ }
5380}
5481
5582module RecursiveFlow = DataFlow:: GlobalWithState< RecursiveConfig > ;
@@ -66,4 +93,4 @@ import RecursiveFlow::PathGraph
6693from RecursiveFlow:: PathNode source , RecursiveFlow:: PathNode sink
6794where RecursiveFlow:: flowPath ( source , sink )
6895// TODO(dm): de-duplicate results
69- select sink .getNode ( ) , source , sink , "Found a recursion: "
96+ select sink .getNode ( ) , source , sink , "Found a recursion: "
0 commit comments