mirror of
https://github.com/github/codeql.git
synced 2026-04-30 19:26:02 +02:00
Java: Implement ContentApprox
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user