Skip to content

Commit

Permalink
Java: Prototype implementation.
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelnebel committed Sep 3, 2024
1 parent cb14cc8 commit 02eb15e
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 7 deletions.
73 changes: 72 additions & 1 deletion java/ql/src/utils/modelgenerator/internal/CaptureModels.qll
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,76 @@ private string printReadAccessPath(PropagateContentFlow::AccessPath ap) {
)
}

string captureContentFlow(DataFlowSummaryTargetApi api) {
pragma[nomagic]
predicate apiContentFlow(
DataFlowSummaryTargetApi api, DataFlow::ParameterNode p, PropagateContentFlow::AccessPath reads,
ReturnNodeExt returnNodeExt, PropagateContentFlow::AccessPath stores, boolean preservesValue
) {
PropagateContentFlow::flow(p, reads, returnNodeExt, stores, preservesValue) and
returnNodeExt.getEnclosingCallable() = api and
p.getEnclosingCallable() = api
}

private class ContentDataFlowSummaryTargetApi extends DataFlowSummaryTargetApi {
ContentDataFlowSummaryTargetApi() {
count(DataFlow::ParameterNode p, ReturnNodeExt returnNodeExt |
apiContentFlow(this, p, _, returnNodeExt, _, _)
) <= 2 * this.getNumberOfParameters() + 3
}
}

private string getSyntheticNames(PropagateContentFlow::AccessPath path) {
exists(PropagateContentFlow::AccessPath tail, ContentSet head |
head = path.getHead() and
tail = path.getTail() and
(
result = getSyntheticNames(tail) or
result = getSyntheticName(head)
)
)
}

/**
* This class models pr type the relevant synthetic names.
* For a synthetic name to relavant for a type, the following must hold:
* 1. The synthetic name must be used both in a read and store.
* 2. The read and store should be in different flows.
*/
private class RelevantSynthetics extends Type {
private PropagateContentFlow::AccessPath reads;
private PropagateContentFlow::AccessPath stores;

RelevantSynthetics() {
exists(
ContentDataFlowSummaryTargetApi api1, DataFlow::ParameterNode p1,
ContentDataFlowSummaryTargetApi api2, DataFlow::ParameterNode p2
|
this = api1.getDeclaringType() and
this = api2.getDeclaringType() and
(api1 != api2 or p1 != p2) and
apiContentFlow(api1, p1, reads, _, _, _) and
apiContentFlow(api2, p2, _, _, stores, _)
)
}

/**
* Gets the relevant synthetic names for this type, if any.
*/
string getRelevantSynthetics() {
result = getSyntheticNames(reads) and result = getSyntheticNames(stores)
}
}

pragma[inline]
private predicate syntheticsMatched(
ContentDataFlowSummaryTargetApi api, PropagateContentFlow::AccessPath path
) {
forall(string synthetic | synthetic = getSyntheticNames(path) |
synthetic = api.getDeclaringType().(RelevantSynthetics).getRelevantSynthetics()
)
}

string captureContentFlow(ContentDataFlowSummaryTargetApi api) {
exists(
DataFlow::ParameterNode p, ReturnNodeExt returnNodeExt, string input, string output,
PropagateContentFlow::AccessPath reads, PropagateContentFlow::AccessPath stores,
Expand All @@ -309,6 +378,8 @@ string captureContentFlow(DataFlowSummaryTargetApi api) {
returnNodeExt.getEnclosingCallable() = api and
input = parameterNodeAsContentInput(p) + printReadAccessPath(reads) and
output = getContentOutput(returnNodeExt) + printStoreAccessPath(stores) and
syntheticsMatched(api, reads) and
syntheticsMatched(api, stores) and
input != output and
result = Printing::asModel(api, input, output, preservesValue)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,16 +340,24 @@ predicate isAdditionalContentFlowStep(DataFlow::Node node1, DataFlow::Node node2
}

/**
* Gets the MaD string representation of the contentset `c`.
* Gets the MaD synthetic name string representation for the contentset `c`, if any.
*/
string getSyntheticName(DataFlow::ContentSet c) {
exists(Field f |
not f.isPublic() and
f = c.(DataFlowUtil::FieldContent).getField() and
result = f.getQualifiedName()
)
or
result = c.(DataFlowUtil::SyntheticFieldContent).getField()
}

string printContent(ContentSet c) {
exists(Field f, string name |
f = c.(DataFlowUtil::FieldContent).getField() and name = f.getQualifiedName()
|
if f.isPublic() then result = "Field[" + name + "]" else result = "SyntheticField[" + name + "]"
exists(Field f | f = c.(DataFlowUtil::FieldContent).getField() and f.isPublic() |
result = "Field[" + f.getQualifiedName() + "]"
)
or
result = "SyntheticField[" + c.(DataFlowUtil::SyntheticFieldContent).getField() + "]"
result = "SyntheticField[" + getSyntheticName(c) + "]"
or
c instanceof DataFlowUtil::CollectionContent and result = "Element"
or
Expand Down

0 comments on commit 02eb15e

Please sign in to comment.