Java: Make synthesized method bodies disjoint from source code.

This commit is contained in:
Anders Schack-Mulligen
2022-08-16 13:36:39 +02:00
parent 28e4224ab1
commit df40ccd129
6 changed files with 56 additions and 25 deletions

View File

@@ -10,7 +10,7 @@ private module DispatchImpl {
DataFlowCallable viableCallable(DataFlowCall c) {
result.asCallable() = VirtualDispatch::viableCallable(c.asCall())
or
result.asCallable().(SummarizedCallable) = c.asCall().getCallee().getSourceDeclaration()
result.asSummarizedCallable() = c.asCall().getCallee().getSourceDeclaration()
}
/**
@@ -118,7 +118,7 @@ private module DispatchImpl {
not failsUnification(t, t2)
)
or
result.asCallable() = def and def instanceof SummarizedCallable
result.asSummarizedCallable() = def
)
}

View File

@@ -13,17 +13,12 @@ newtype TNode =
not e.getType() instanceof VoidType and
not e.getParent*() instanceof Annotation
} or
TExplicitParameterNode(Parameter p) {
exists(p.getCallable().getBody()) or p.getCallable() instanceof SummarizedCallable
} or
TExplicitParameterNode(Parameter p) { exists(p.getCallable().getBody()) } or
TImplicitVarargsArray(Call c) {
c.getCallee().isVarargs() and
not exists(Argument arg | arg.getCall() = c and arg.isExplicitVarargsArray())
} or
TInstanceParameterNode(Callable c) {
(exists(c.getBody()) or c instanceof SummarizedCallable) and
not c.isStatic()
} or
TInstanceParameterNode(Callable c) { exists(c.getBody()) and not c.isStatic() } or
TImplicitInstanceAccess(InstanceAccessExt ia) { not ia.isExplicit(_) } or
TMallocNode(ClassInstanceExpr cie) or
TExplicitExprPostUpdate(Expr e) {
@@ -45,6 +40,9 @@ newtype TNode =
TSummaryInternalNode(SummarizedCallable c, FlowSummaryImpl::Private::SummaryNodeState state) {
FlowSummaryImpl::Private::summaryNodeRange(c, state)
} or
TSummaryParameterNode(SummarizedCallable c, int pos) {
FlowSummaryImpl::Private::summaryParameterNodeRange(c, pos)
} or
TFieldValueNode(Field f)
private predicate explicitInstanceArgument(Call call, Expr instarg) {
@@ -96,6 +94,8 @@ module Public {
or
result = this.(ImplicitPostUpdateNode).getPreUpdateNode().getType()
or
result = this.(SummaryParameterNode).getTypeImpl()
or
result = this.(FieldValueNode).getField().getType()
}
@@ -155,7 +155,7 @@ module Public {
* Holds if this node is the parameter of `c` at the specified (zero-based)
* position. The implicit `this` parameter is considered to have index `-1`.
*/
abstract predicate isParameterOf(Callable c, int pos);
abstract predicate isParameterOf(DataFlowCallable c, int pos);
}
/**
@@ -173,7 +173,9 @@ module Public {
/** Gets the parameter corresponding to this node. */
Parameter getParameter() { result = param }
override predicate isParameterOf(Callable c, int pos) { c.getParameter(pos) = param }
override predicate isParameterOf(DataFlowCallable c, int pos) {
c.asCallable().getParameter(pos) = param
}
}
/** Gets the node corresponding to `p`. */
@@ -213,7 +215,9 @@ module Public {
/** Gets the callable containing this `this` parameter. */
Callable getCallable() { result = callable }
override predicate isParameterOf(Callable c, int pos) { callable = c and pos = -1 }
override predicate isParameterOf(DataFlowCallable c, int pos) {
callable = c.asCallable() and pos = -1
}
}
/**
@@ -336,13 +340,14 @@ module Private {
result.asCallable() = n.(ImplicitInstanceAccess).getInstanceAccess().getEnclosingCallable() or
result.asCallable() = n.(MallocNode).getClassInstanceExpr().getEnclosingCallable() or
result = nodeGetEnclosingCallable(n.(ImplicitPostUpdateNode).getPreUpdateNode()) or
n = TSummaryInternalNode(result.asCallable(), _) or
n = TSummaryInternalNode(result.asSummarizedCallable(), _) or
n = TSummaryParameterNode(result.asSummarizedCallable(), _) or
result.asFieldScope() = n.(FieldValueNode).getField()
}
/** Holds if `p` is a `ParameterNode` of `c` with position `pos`. */
predicate isParameterNode(ParameterNode p, DataFlowCallable c, ParameterPosition pos) {
p.isParameterOf(c.asCallable(), pos)
p.isParameterOf(c, pos)
}
/** Holds if `arg` is an `ArgumentNode` of `c` with position `pos`. */
@@ -443,6 +448,27 @@ module Private {
SummaryNode getSummaryNode(SummarizedCallable c, FlowSummaryImpl::Private::SummaryNodeState state) {
result = TSummaryInternalNode(c, state)
}
class SummaryParameterNode extends ParameterNode, TSummaryParameterNode {
private SummarizedCallable sc;
private int pos_;
SummaryParameterNode() { this = TSummaryParameterNode(sc, pos_) }
override Location getLocation() { result = sc.getLocation() }
override string toString() { result = "[summary param] " + pos_ + " in " + sc }
override predicate isParameterOf(DataFlowCallable c, int pos) {
c.asSummarizedCallable() = sc and pos = pos_
}
Type getTypeImpl() {
result = sc.getParameter(pos_).getType()
or
pos_ = -1 and result = sc.getDeclaringType()
}
}
}
private import Private

View File

@@ -230,26 +230,32 @@ class CastNode extends ExprNode {
}
private newtype TDataFlowCallable =
TCallable(Callable c) or
TSrcCallable(Callable c) or
TSummarizedCallable(SummarizedCallable c) or
TFieldScope(Field f)
class DataFlowCallable extends TDataFlowCallable {
Callable asCallable() { this = TCallable(result) }
Callable asCallable() { this = TSrcCallable(result) }
SummarizedCallable asSummarizedCallable() { this = TSummarizedCallable(result) }
Field asFieldScope() { this = TFieldScope(result) }
RefType getDeclaringType() {
result = this.asCallable().getDeclaringType() or
result = this.asSummarizedCallable().getDeclaringType() or
result = this.asFieldScope().getDeclaringType()
}
string toString() {
result = this.asCallable().toString() or
result = "Synthetic: " + this.asSummarizedCallable().toString() or
result = "Field scope: " + this.asFieldScope().toString()
}
Location getLocation() {
result = this.asCallable().getLocation() or
result = this.asSummarizedCallable().getLocation() or
result = this.asFieldScope().getLocation()
}
}
@@ -317,7 +323,7 @@ class SummaryCall extends DataFlowCall, TSummaryCall {
/** Gets the data flow node that this call targets. */
Node getReceiver() { result = receiver }
override DataFlowCallable getEnclosingCallable() { result.asCallable() = c }
override DataFlowCallable getEnclosingCallable() { result.asSummarizedCallable() = c }
override string toString() { result = "[summary] call to " + receiver + " in " + c }
@@ -376,9 +382,8 @@ predicate forceHighPrecision(Content c) {
/** Holds if `n` should be hidden from path explanations. */
predicate nodeIsHidden(Node n) {
n instanceof SummaryNode
or
n.(ParameterNode).isParameterOf(any(SummarizedCallable c), _)
n instanceof SummaryNode or
n instanceof SummaryParameterNode
}
class LambdaCallKind = Method; // the "apply" method in the functional interface

View File

@@ -16,7 +16,7 @@ private module FlowSummaries {
class SummarizedCallableBase = Callable;
DataFlowCallable inject(SummarizedCallable c) { result.asCallable() = c }
DataFlowCallable inject(SummarizedCallable c) { result.asSummarizedCallable() = c }
/** Gets the parameter position of the instance parameter. */
int instanceParameterPosition() { result = -1 }

View File

@@ -131,8 +131,8 @@ private class RelevantNode extends Node {
*/
pragma[nomagic]
private predicate viableParamCand(Call call, int i, ParameterNode p) {
exists(Callable callable |
callable = dispatchCand(call) and
exists(DataFlowCallable callable |
callable.asCallable() = dispatchCand(call) and
p.isParameterOf(callable, i) and
p instanceof RelevantNode
)

View File

@@ -33,8 +33,8 @@ private Callable dispatchCand(Call c) {
*/
pragma[nomagic]
private predicate viableParam(Call call, int i, ParameterNode p) {
exists(Callable callable |
callable = dispatchCand(call) and
exists(DataFlowCallable callable |
callable.asCallable() = dispatchCand(call) and
p.isParameterOf(callable, i)
)
}