Skip to content

Commit a27dac0

Browse files
committed
Java: Use shared flow summary library for csv models.
1 parent 36abf87 commit a27dac0

File tree

4 files changed

+79
-21
lines changed

4 files changed

+79
-21
lines changed

java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll

Lines changed: 74 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
import java
6868
private import semmle.code.java.dataflow.DataFlow::DataFlow
6969
private import internal.DataFlowPrivate
70+
private import FlowSummary
7071

7172
/**
7273
* A module importing the frameworks that provide external flow data,
@@ -459,7 +460,8 @@ module CsvValidation {
459460
summaryModel(_, _, _, _, _, _, input, _, _) and pred = "summary"
460461
|
461462
specSplit(input, part, _) and
462-
not part.regexpMatch("|Argument|ReturnValue") and
463+
not part.regexpMatch("|ReturnValue|ArrayElement|Element") and
464+
not (part = "Argument" and pred = "sink") and
463465
not parseArg(part, _) and
464466
msg = "Unrecognized input specification \"" + part + "\" in " + pred + " model."
465467
)
@@ -470,7 +472,8 @@ module CsvValidation {
470472
summaryModel(_, _, _, _, _, _, _, output, _) and pred = "summary"
471473
|
472474
specSplit(output, part, _) and
473-
not part.regexpMatch("|Argument|Parameter|ReturnValue") and
475+
not part.regexpMatch("|ReturnValue|ArrayElement|Element") and
476+
not (part = ["Argument", "Parameter"] and pred = "source") and
474477
not parseArg(part, _) and
475478
not parseParam(part, _) and
476479
msg = "Unrecognized output specification \"" + part + "\" in " + pred + " model."
@@ -675,6 +678,75 @@ private predicate summaryElementRef(Top ref, string input, string output, string
675678
)
676679
}
677680

681+
private SummaryComponent interpretComponent(string c) {
682+
specSplit(_, c, _) and
683+
(
684+
exists(int pos | parseArg(c, pos) and result = SummaryComponent::argument(pos))
685+
or
686+
exists(int pos | parseParam(c, pos) and result = SummaryComponent::parameter(pos))
687+
or
688+
c = "ReturnValue" and result = SummaryComponent::return()
689+
or
690+
c = "ArrayElement" and result = SummaryComponent::content(any(ArrayContent c0))
691+
or
692+
c = "Element" and result = SummaryComponent::content(any(CollectionContent c0))
693+
// or
694+
// c = "MapKey" and result = SummaryComponent::content(any(MapKeyContent c0))
695+
// or
696+
// c = "MapValue" and result = SummaryComponent::content(any(MapValueContent c0))
697+
)
698+
}
699+
700+
private predicate interpretSpec(string spec, int idx, SummaryComponentStack stack) {
701+
exists(string c |
702+
summaryElement(_, spec, _, _) or
703+
summaryElement(_, _, spec, _)
704+
|
705+
len(spec, idx + 1) and
706+
specSplit(spec, c, idx) and
707+
stack = SummaryComponentStack::singleton(interpretComponent(c))
708+
)
709+
or
710+
exists(SummaryComponent head, SummaryComponentStack tail |
711+
interpretSpec(spec, idx, head, tail) and
712+
stack = SummaryComponentStack::push(head, tail)
713+
)
714+
}
715+
716+
private predicate interpretSpec(
717+
string output, int idx, SummaryComponent head, SummaryComponentStack tail
718+
) {
719+
exists(string c |
720+
interpretSpec(output, idx + 1, tail) and
721+
specSplit(output, c, idx) and
722+
head = interpretComponent(c)
723+
)
724+
}
725+
726+
private class MkStack extends RequiredSummaryComponentStack {
727+
MkStack() { interpretSpec(_, _, _, this) }
728+
729+
override predicate required(SummaryComponent c) { interpretSpec(_, _, c, this) }
730+
}
731+
732+
private class SummarizedCallableExternal extends SummarizedCallable {
733+
SummarizedCallableExternal() { summaryElement(this, _, _, _) }
734+
735+
override predicate propagatesFlow(
736+
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue
737+
) {
738+
exists(string inSpec, string outSpec, string kind |
739+
summaryElement(this, inSpec, outSpec, kind) and
740+
interpretSpec(inSpec, 0, input) and
741+
interpretSpec(outSpec, 0, output)
742+
|
743+
kind = "value" and preservesValue = true
744+
or
745+
kind = "taint" and preservesValue = false
746+
)
747+
}
748+
}
749+
678750
private newtype TAstOrNode =
679751
TAst(Top t) or
680752
TNode(Node n)
@@ -761,15 +833,3 @@ predicate sinkNode(Node node, string kind) {
761833
interpretInput(input, 0, ref, TNode(node))
762834
)
763835
}
764-
765-
/**
766-
* Holds if `node1` to `node2` is specified as a flow step with the given kind
767-
* in a CSV flow model.
768-
*/
769-
predicate summaryStep(Node node1, Node node2, string kind) {
770-
exists(Top ref, string input, string output |
771-
summaryElementRef(ref, input, output, kind) and
772-
interpretInput(input, 0, ref, TNode(node1)) and
773-
interpretOutput(output, 0, ref, TNode(node2))
774-
)
775-
}

java/ql/src/semmle/code/java/dataflow/FlowSummary.qll

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ private import internal.DataFlowDispatch
88
private import internal.DataFlowPrivate
99

1010
// import all instances below
11-
private module Summaries { }
11+
private module Summaries {
12+
private import semmle.code.java.dataflow.ExternalFlow
13+
}
1214

1315
class SummaryComponent = Impl::Public::SummaryComponent;
1416

java/ql/src/semmle/code/java/dataflow/internal/DataFlowUtil.qll

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,6 @@ predicate simpleLocalFlowStep(Node node1, Node node2) {
142142
or
143143
node2.asExpr().(AssignExpr).getSource() = node1.asExpr()
144144
or
145-
summaryStep(node1, node2, "value")
146-
or
147145
exists(MethodAccess ma, ValuePreservingMethod m, int argNo |
148146
ma.getCallee().getSourceDeclaration() = m and m.returnsValue(argNo)
149147
|

java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,14 @@ private predicate localAdditionalBasicTaintStep(DataFlow::Node src, DataFlow::No
5757
localAdditionalTaintUpdateStep(src.asExpr(),
5858
sink.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr())
5959
or
60-
summaryStep(src, sink, "taint") and
61-
not summaryStep(src, sink, "value")
62-
or
6360
exists(Argument arg |
6461
src.asExpr() = arg and
6562
arg.isVararg() and
6663
sink.(DataFlow::ImplicitVarargsArray).getCall() = arg.getCall()
6764
)
6865
or
69-
FlowSummaryImpl::Private::Steps::summaryLocalStep(src, sink, false)
66+
FlowSummaryImpl::Private::Steps::summaryLocalStep(src, sink, false) and
67+
not FlowSummaryImpl::Private::Steps::summaryLocalStep(src, sink, true)
7068
}
7169

7270
/**

0 commit comments

Comments
 (0)