Java: Add support for synthetic fields in csv rows.

This commit is contained in:
Anders Schack-Mulligen
2021-07-15 12:19:34 +02:00
parent d34e748c83
commit 7339bd89ba
3 changed files with 72 additions and 36 deletions

View File

@@ -652,6 +652,48 @@ Element interpretElement(
)
}
private predicate parseField(string c, FieldContent f) {
specSplit(_, c, _) and
exists(string fieldRegex, string package, string className, string fieldName |
fieldRegex = "^Field\\[(.*)\\.([^.]+)\\.([^.]+)\\]$" and
package = c.regexpCapture(fieldRegex, 1) and
className = c.regexpCapture(fieldRegex, 2) and
fieldName = c.regexpCapture(fieldRegex, 3) and
f.getField().hasQualifiedName(package, className, fieldName)
)
}
/** A string representing a synthetic instance field. */
class SyntheticField extends string {
SyntheticField() { parseSynthField(_, this) }
/**
* Gets the type of this field. The default type is `Object`, but this can be
* overridden.
*/
Type getType() { result instanceof TypeObject }
}
private predicate parseSynthField(string c, string f) {
specSplit(_, c, _) and
c.regexpCapture("SyntheticField\\[([.a-zA-Z0-9]+)\\]", 1) = f
}
/** Holds if the specification component parses as a `Content`. */
predicate parseContent(string component, Content content) {
parseField(component, content)
or
parseSynthField(component, content.(SyntheticFieldContent).getField())
or
component = "ArrayElement" and content instanceof ArrayContent
or
component = "Element" and content instanceof CollectionContent
or
component = "MapKey" and content instanceof MapKeyContent
or
component = "MapValue" and content instanceof MapValueContent
}
cached
private module Cached {
/**

View File

@@ -162,7 +162,8 @@ private newtype TContent =
TArrayContent() or
TCollectionContent() or
TMapKeyContent() or
TMapValueContent()
TMapValueContent() or
TSyntheticFieldContent(SyntheticField s)
/**
* A description of the way data may be stored inside an object. Examples
@@ -170,6 +171,9 @@ private newtype TContent =
* of an array.
*/
class Content extends TContent {
/** Gets the type of the contained data for the purpose of type pruning. */
abstract DataFlowType getType();
/** Gets a textual representation of this element. */
abstract string toString();
@@ -193,6 +197,8 @@ class FieldContent extends Content, TFieldContent {
InstanceField getField() { result = f }
override DataFlowType getType() { result = getErasedRepr(f.getType()) }
override string toString() { result = f.toString() }
override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
@@ -202,24 +208,45 @@ class FieldContent extends Content, TFieldContent {
/** A reference through an array. */
class ArrayContent extends Content, TArrayContent {
override DataFlowType getType() { result instanceof TypeObject }
override string toString() { result = "[]" }
}
/** A reference through the contents of some collection-like container. */
class CollectionContent extends Content, TCollectionContent {
override DataFlowType getType() { result instanceof TypeObject }
override string toString() { result = "<element>" }
}
/** A reference through a map key. */
class MapKeyContent extends Content, TMapKeyContent {
override DataFlowType getType() { result instanceof TypeObject }
override string toString() { result = "<map.key>" }
}
/** A reference through a map value. */
class MapValueContent extends Content, TMapValueContent {
override DataFlowType getType() { result instanceof TypeObject }
override string toString() { result = "<map.value>" }
}
/** A reference through a synthetic instance field. */
class SyntheticFieldContent extends Content, TSyntheticFieldContent {
SyntheticField s;
SyntheticFieldContent() { this = TSyntheticFieldContent(s) }
SyntheticField getField() { result = s }
override DataFlowType getType() { result = getErasedRepr(s.getType()) }
override string toString() { result = s.toString() }
}
/**
* A guard that validates some expression.
*

View File

@@ -23,21 +23,7 @@ Node summaryNode(SummarizedCallable c, SummaryNodeState state) { result = getSum
DataFlowCall summaryDataFlowCall(Node receiver) { none() }
/** Gets the type of content `c`. */
DataFlowType getContentType(Content c) {
result = getErasedRepr(c.(FieldContent).getField().getType())
or
c instanceof CollectionContent and
result instanceof TypeObject
or
c instanceof ArrayContent and
result instanceof TypeObject
or
c instanceof MapKeyContent and
result instanceof TypeObject
or
c instanceof MapValueContent and
result instanceof TypeObject
}
DataFlowType getContentType(Content c) { result = c.getType() }
/** Gets the return type of kind `rk` for callable `c`. */
DataFlowType getReturnType(SummarizedCallable c, ReturnKind rk) {
@@ -70,29 +56,10 @@ predicate summaryElement(DataFlowCallable c, string input, string output, string
)
}
private FieldContent parseField(string c) {
External::specSplit(_, c, _) and
exists(string fieldRegex, string package, string className, string fieldName |
fieldRegex = "^Field\\[(.*)\\.([^.]+)\\.([^.]+)\\]$" and
package = c.regexpCapture(fieldRegex, 1) and
className = c.regexpCapture(fieldRegex, 2) and
fieldName = c.regexpCapture(fieldRegex, 3) and
result.getField().hasQualifiedName(package, className, fieldName)
)
}
/** Gets the summary component for specification component `c`, if any. */
bindingset[c]
SummaryComponent interpretComponentSpecific(string c) {
result = SummaryComponent::content(parseField(c))
or
c = "ArrayElement" and result = SummaryComponent::content(any(ArrayContent c0))
or
c = "Element" and result = SummaryComponent::content(any(CollectionContent c0))
or
c = "MapKey" and result = SummaryComponent::content(any(MapKeyContent c0))
or
c = "MapValue" and result = SummaryComponent::content(any(MapValueContent c0))
exists(Content content | parseContent(c, content) and result = SummaryComponent::content(content))
}
class SourceOrSinkElement = Top;