Java: Implement ContentApprox

This commit is contained in:
Tom Hvitved
2022-12-09 10:43:16 +01:00
parent 4d2436dd82
commit 2a28953e41
3 changed files with 109 additions and 45 deletions

View File

@@ -1,49 +1,77 @@
private import java
private import semmle.code.java.dataflow.InstanceAccess
private import semmle.code.java.dataflow.ExternalFlow
private import semmle.code.java.dataflow.FlowSummary
private import semmle.code.java.dataflow.TypeFlow
private import DataFlowPrivate
private import DataFlowUtil
private import FlowSummaryImpl as FlowSummaryImpl
private import DataFlowImplCommon as DataFlowImplCommon
/** Gets a string for approximating the name of a field. */
string approximateFieldContent(FieldContent fc) { result = fc.getField().getName().prefix(1) }
cached
newtype TNode =
TExprNode(Expr e) {
DataFlowImplCommon::forceCachingInSameStage() and
not e.getType() instanceof VoidType and
not e.getParent*() instanceof Annotation
} 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()) and not c.isStatic() } or
TImplicitInstanceAccess(InstanceAccessExt ia) { not ia.isExplicit(_) } or
TMallocNode(ClassInstanceExpr cie) or
TExplicitExprPostUpdate(Expr e) {
explicitInstanceArgument(_, e)
or
e instanceof Argument and not e.getType() instanceof ImmutableType
or
exists(FieldAccess fa | fa.getField() instanceof InstanceField and e = fa.getQualifier())
or
exists(ArrayAccess aa | e = aa.getArray())
} or
TImplicitExprPostUpdate(InstanceAccessExt ia) {
implicitInstanceArgument(_, ia)
or
exists(FieldAccess fa |
fa.getField() instanceof InstanceField and ia.isImplicitFieldQualifier(fa)
)
} or
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 module Cached {
cached
newtype TNode =
TExprNode(Expr e) {
DataFlowImplCommon::forceCachingInSameStage() and
not e.getType() instanceof VoidType and
not e.getParent*() instanceof Annotation
} 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()) and not c.isStatic() } or
TImplicitInstanceAccess(InstanceAccessExt ia) { not ia.isExplicit(_) } or
TMallocNode(ClassInstanceExpr cie) or
TExplicitExprPostUpdate(Expr e) {
explicitInstanceArgument(_, e)
or
e instanceof Argument and not e.getType() instanceof ImmutableType
or
exists(FieldAccess fa | fa.getField() instanceof InstanceField and e = fa.getQualifier())
or
exists(ArrayAccess aa | e = aa.getArray())
} or
TImplicitExprPostUpdate(InstanceAccessExt ia) {
implicitInstanceArgument(_, ia)
or
exists(FieldAccess fa |
fa.getField() instanceof InstanceField and ia.isImplicitFieldQualifier(fa)
)
} or
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)
cached
newtype TContent =
TFieldContent(InstanceField f) or
TArrayContent() or
TCollectionContent() or
TMapKeyContent() or
TMapValueContent() or
TSyntheticFieldContent(SyntheticField s)
cached
newtype TContentApprox =
TFieldContentApprox(string firstChar) { firstChar = approximateFieldContent(_) } or
TArrayContentApprox() or
TCollectionContentApprox() or
TMapKeyContentApprox() or
TMapValueContentApprox() or
TSyntheticFieldApproxContent()
}
import Cached
private predicate explicitInstanceArgument(Call call, Expr instarg) {
call instanceof MethodAccess and

View File

@@ -9,6 +9,7 @@ private import semmle.code.java.dataflow.FlowSteps
private import semmle.code.java.dataflow.FlowSummary
private import FlowSummaryImpl as FlowSummaryImpl
private import DataFlowImplConsistency
private import DataFlowNodes
import DataFlowNodes::Private
private newtype TReturnKind = TNormalReturnKind()
@@ -420,6 +421,48 @@ predicate allowParameterReturnInSelf(ParameterNode p) {
FlowSummaryImpl::Private::summaryAllowParameterReturnInSelf(p)
}
/** An approximated `Content`. */
class ContentApprox extends TContentApprox {
/** Gets a textual representation of this approximated `Content`. */
string toString() {
exists(string firstChar |
this = TFieldContentApprox(firstChar) and
result = "approximated field " + firstChar
)
or
this = TArrayContentApprox() and
result = "[]"
or
this = TCollectionContentApprox() and
result = "<element>"
or
this = TMapKeyContentApprox() and
result = "<map.key>"
or
this = TMapValueContentApprox() and
result = "<map.value>"
or
this = TSyntheticFieldApproxContent() and
result = "approximated synthetic field"
}
}
/** Gets an approximated value for content `c`. */
pragma[nomagic]
ContentApprox getContentApprox(Content c) {
result = TFieldContentApprox(approximateFieldContent(c))
or
c instanceof ArrayContent and result = TArrayContentApprox()
or
c instanceof CollectionContent and result = TCollectionContentApprox()
or
c instanceof MapKeyContent and result = TMapKeyContentApprox()
or
c instanceof MapValueContent and result = TMapValueContentApprox()
or
c instanceof SyntheticFieldContent and result = TSyntheticFieldApproxContent()
}
private class MyConsistencyConfiguration extends Consistency::ConsistencyConfiguration {
override predicate argHasPostUpdateExclude(ArgumentNode n) {
n.getType() instanceof ImmutableType or n instanceof ImplicitVarargsArray

View File

@@ -12,6 +12,7 @@ private import semmle.code.java.dataflow.FlowSummary
private import semmle.code.java.dataflow.InstanceAccess
private import FlowSummaryImpl as FlowSummaryImpl
private import TaintTrackingUtil as TaintTrackingUtil
private import DataFlowNodes
import DataFlowNodes::Public
import semmle.code.Unit
@@ -186,14 +187,6 @@ private predicate simpleLocalFlowStep0(Node node1, Node node2) {
FlowSummaryImpl::Private::Steps::summaryLocalStep(node1, node2, true)
}
private newtype TContent =
TFieldContent(InstanceField f) or
TArrayContent() or
TCollectionContent() or
TMapKeyContent() or
TMapValueContent() or
TSyntheticFieldContent(SyntheticField s)
/**
* A description of the way data may be stored inside an object. Examples
* include instance fields, the contents of a collection object, or the contents