Skip to content

Commit 7228766

Browse files
kaspersvaschackmull
authored andcommitted
Data flow: Implement new lambda flow interface for Java
1 parent 15c8968 commit 7228766

File tree

3 files changed

+64
-4
lines changed

3 files changed

+64
-4
lines changed

java/ql/lib/semmle/code/java/dataflow/internal/DataFlowNodes.qll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ private import semmle.code.java.dataflow.TypeFlow
66
private import semmle.code.java.dataflow.FlowSteps
77
private import DataFlowPrivate
88
private import DataFlowUtil
9+
private import DataFlowDispatch
910
private import FlowSummaryImpl as FlowSummaryImpl
1011
private import DataFlowImplCommon as DataFlowImplCommon
1112
private import semmle.code.java.controlflow.Guards
@@ -68,7 +69,9 @@ private module Cached {
6869
TMapKeyContent() or
6970
TMapValueContent() or
7071
TCapturedVariableContent(CapturedVariable v) or
71-
TSyntheticFieldContent(SyntheticField s)
72+
TSyntheticFieldContent(SyntheticField s) or
73+
TLambdaReturn(Method m) or
74+
TLambdaArgument(Method m, ArgumentPosition pos)
7275

7376
cached
7477
newtype TContentApprox =

java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,8 @@ private newtype TDataFlowCall =
464464
TCall(Call c) or
465465
TSummaryCall(SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver) {
466466
FlowSummaryImpl::Private::summaryCallbackRange(c, receiver)
467-
}
467+
} or
468+
TLambdaSynthCall(Node node) { lambdaCreationHelper(node, _, _) }
468469

469470
/** A call relevant for data flow. Includes both source calls and synthesized calls. */
470471
class DataFlowCall extends TDataFlowCall {
@@ -526,6 +527,19 @@ class SummaryCall extends DataFlowCall, TSummaryCall {
526527
override Location getLocation() { result = c.getLocation() }
527528
}
528529

530+
/** A synthesized call inside a `SummarizedCallable`. */
531+
class LambdaSynthCall extends DataFlowCall, TLambdaSynthCall {
532+
private Node node;
533+
534+
LambdaSynthCall() { this = TLambdaSynthCall(node) }
535+
536+
override DataFlowCallable getEnclosingCallable() { result.asCallable() = node.getEnclosingCallable() }
537+
538+
override string toString() { result = "[synthetic] call to " + node }
539+
540+
override Location getLocation() { result = node.getLocation() }
541+
}
542+
529543
class NodeRegion instanceof BasicBlock {
530544
string toString() { result = "NodeRegion" }
531545

@@ -585,8 +599,7 @@ predicate nodeIsHidden(Node n) { n instanceof FlowSummaryNode }
585599

586600
class LambdaCallKind = Method; // the "apply" method in the functional interface
587601

588-
/** Holds if `creation` is an expression that creates a lambda of kind `kind` for `c`. */
589-
predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) {
602+
predicate lambdaCreationHelper(Node creation, LambdaCallKind kind, DataFlowCallable c) {
590603
exists(ClassInstanceExpr func, Interface t, FunctionalInterface interface |
591604
creation.asExpr() = func and
592605
func.getAnonymousClass().getAMethod() = c.asCallable() and
@@ -597,6 +610,12 @@ predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c)
597610
)
598611
}
599612

613+
/** Holds if `creation` is an expression that creates a lambda of kind `kind` for `c`. */
614+
predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c, DataFlowCall synthCall) {
615+
synthCall = TLambdaSynthCall(creation) and
616+
lambdaCreationHelper(creation, kind, c)
617+
}
618+
600619
/** Holds if `call` is a lambda call of kind `kind` where `receiver` is the lambda expression. */
601620
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
602621
receiver.(FlowSummaryNode).getSummaryNode() = call.(SummaryCall).getReceiver() and
@@ -766,3 +785,15 @@ predicate containerContent(ContentSet c) {
766785
c instanceof MapKeyContent or
767786
c instanceof MapValueContent
768787
}
788+
789+
Content getLambdaReturnContent(LambdaCallKind kind) {
790+
result = TLambdaReturn(kind)
791+
}
792+
793+
Content getLambdaArgumentContent(LambdaCallKind kind, ArgumentPosition pos) {
794+
result = TLambdaArgument(kind, pos)
795+
}
796+
797+
predicate isLambdaInstanceParameter(ParameterNode p) {
798+
exists(DataFlowCallable c | lambdaCreationHelper(_, _, c) and p.isParameterOf(c, -1))
799+
}

java/ql/lib/semmle/code/java/dataflow/internal/DataFlowUtil.qll

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
private import java
66
private import DataFlowPrivate
7+
private import DataFlowDispatch
78
private import semmle.code.java.dataflow.SSA
89
private import semmle.code.java.controlflow.Guards
910
private import semmle.code.java.dataflow.ExternalFlow
@@ -359,6 +360,31 @@ class SyntheticFieldContent extends Content, TSyntheticFieldContent {
359360
override string toString() { result = s.toString() }
360361
}
361362

363+
class LambdaReturnContent extends Content, TLambdaReturn {
364+
Method m;
365+
366+
LambdaReturnContent() { this = TLambdaReturn(m) }
367+
368+
override DataFlowType getType() {
369+
result = getErasedRepr(m.getReturnType())
370+
}
371+
372+
override string toString() { result = "<lambda-return>" }
373+
}
374+
375+
class LambdaArgumentContent extends Content, TLambdaArgument {
376+
Method m;
377+
ArgumentPosition pos;
378+
379+
LambdaArgumentContent() {
380+
this = TLambdaArgument(m, pos)
381+
}
382+
383+
override DataFlowType getType() {
384+
result = getErasedRepr(m.getParameter(pos).getType())
385+
}
386+
override string toString() { result = "<lambda-argument>" + pos.toString() }
387+
}
362388
/**
363389
* An entity that represents a set of `Content`s.
364390
*

0 commit comments

Comments
 (0)