Skip to content

Commit f7278d3

Browse files
authored
Merge pull request #2498 from aschackmull/java/taint-getter
Java/C++/C#: Add support for taint-getter/setter summaries in data flow.
2 parents 5a5832b + 241b8a0 commit f7278d3

31 files changed

+11235
-3581
lines changed

cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll

Lines changed: 567 additions & 176 deletions
Large diffs are not rendered by default.

cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll

Lines changed: 567 additions & 176 deletions
Large diffs are not rendered by default.

cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll

Lines changed: 567 additions & 176 deletions
Large diffs are not rendered by default.

cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll

Lines changed: 567 additions & 176 deletions
Large diffs are not rendered by default.

cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll

Lines changed: 95 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,6 @@ private module ImplCommon {
112112
enclosing = arg.getEnclosingCallable()
113113
}
114114

115-
pragma[noinline]
116-
private ParameterNode getAParameter(DataFlowCallable c) { result.getEnclosingCallable() = c }
117-
118115
pragma[noinline]
119116
private predicate viableParamArg0(
120117
int i, ArgumentNode arg, CallContext outercc, DataFlowCall call
@@ -123,9 +120,9 @@ private module ImplCommon {
123120
(
124121
outercc = TAnyCallContext()
125122
or
126-
outercc = TSomeCall(getAParameter(c), _)
123+
outercc = TSomeCall()
127124
or
128-
exists(DataFlowCall other | outercc = TSpecificCall(other, _, _) |
125+
exists(DataFlowCall other | outercc = TSpecificCall(other) |
129126
recordDataFlowCallSite(other, c)
130127
)
131128
) and
@@ -156,17 +153,17 @@ private module ImplCommon {
156153
viableParamArg1(p, callable, i, arg, outercc, call)
157154
|
158155
if recordDataFlowCallSite(call, callable)
159-
then innercc = TSpecificCall(call, i, true)
160-
else innercc = TSomeCall(p, true)
156+
then innercc = TSpecificCall(call)
157+
else innercc = TSomeCall()
161158
)
162159
}
163160

164161
private CallContextCall getAValidCallContextForParameter(ParameterNode p) {
165-
result = TSomeCall(p, _)
162+
result = TSomeCall()
166163
or
167-
exists(DataFlowCall call, int i, DataFlowCallable callable |
168-
result = TSpecificCall(call, i, _) and
169-
p.isParameterOf(callable, i) and
164+
exists(DataFlowCall call, DataFlowCallable callable |
165+
result = TSpecificCall(call) and
166+
p.isParameterOf(callable, _) and
170167
recordDataFlowCallSite(call, callable)
171168
)
172169
}
@@ -460,9 +457,6 @@ private module ImplCommon {
460457
enclosing = arg.getEnclosingCallable()
461458
}
462459

463-
pragma[noinline]
464-
private ParameterNode getAParameter(DataFlowCallable c) { result.getEnclosingCallable() = c }
465-
466460
pragma[noinline]
467461
private predicate viableParamArg0(
468462
int i, ArgumentNode arg, CallContext outercc, DataFlowCall call
@@ -471,9 +465,9 @@ private module ImplCommon {
471465
(
472466
outercc = TAnyCallContext()
473467
or
474-
outercc = TSomeCall(getAParameter(c), _)
468+
outercc = TSomeCall()
475469
or
476-
exists(DataFlowCall other | outercc = TSpecificCall(other, _, _) |
470+
exists(DataFlowCall other | outercc = TSpecificCall(other) |
477471
recordDataFlowCallSite(other, c)
478472
)
479473
) and
@@ -504,17 +498,17 @@ private module ImplCommon {
504498
viableParamArg1(p, callable, i, arg, outercc, call)
505499
|
506500
if recordDataFlowCallSite(call, callable)
507-
then innercc = TSpecificCall(call, i, true)
508-
else innercc = TSomeCall(p, true)
501+
then innercc = TSpecificCall(call)
502+
else innercc = TSomeCall()
509503
)
510504
}
511505

512506
private CallContextCall getAValidCallContextForParameter(ParameterNode p) {
513-
result = TSomeCall(p, _)
507+
result = TSomeCall()
514508
or
515-
exists(DataFlowCall call, int i, DataFlowCallable callable |
516-
result = TSpecificCall(call, i, _) and
517-
p.isParameterOf(callable, i) and
509+
exists(DataFlowCall call, DataFlowCallable callable |
510+
result = TSpecificCall(call) and
511+
p.isParameterOf(callable, _) and
518512
recordDataFlowCallSite(call, callable)
519513
)
520514
}
@@ -579,14 +573,6 @@ private module ImplCommon {
579573
}
580574
}
581575

582-
/**
583-
* Holds if `call` passes an implicit or explicit instance argument, i.e., an
584-
* expression that reaches a `this` parameter.
585-
*/
586-
private predicate callHasInstanceArgument(DataFlowCall call) {
587-
exists(ArgumentNode arg | arg.argumentOf(call, -1))
588-
}
589-
590576
/**
591577
* Holds if the call context `call` either improves virtual dispatch in
592578
* `callable` or if it allows us to prune unreachable nodes in `callable`.
@@ -601,16 +587,8 @@ private module ImplCommon {
601587
cached
602588
newtype TCallContext =
603589
TAnyCallContext() or
604-
TSpecificCall(DataFlowCall call, int i, boolean emptyAp) {
605-
recordDataFlowCallSite(call, _) and
606-
(emptyAp = true or emptyAp = false) and
607-
(
608-
exists(call.getArgument(i))
609-
or
610-
i = -1 and callHasInstanceArgument(call)
611-
)
612-
} or
613-
TSomeCall(ParameterNode p, boolean emptyAp) { emptyAp = true or emptyAp = false } or
590+
TSpecificCall(DataFlowCall call) { recordDataFlowCallSite(call, _) } or
591+
TSomeCall() or
614592
TReturn(DataFlowCallable c, DataFlowCall call) { reducedViableImplInReturn(c, call) }
615593

616594
cached
@@ -635,11 +613,11 @@ private module ImplCommon {
635613
*
636614
* There are four cases:
637615
* - `TAnyCallContext()` : No restrictions on method flow.
638-
* - `TSpecificCall(DataFlowCall call, int i)` : Flow entered through the `i`th
639-
* parameter at the given `call`. This call improves the set of viable
616+
* - `TSpecificCall(DataFlowCall call)` : Flow entered through the
617+
* given `call`. This call improves the set of viable
640618
* dispatch targets for at least one method call in the current callable
641619
* or helps prune unreachable nodes in the current callable.
642-
* - `TSomeCall(ParameterNode p)` : Flow entered through parameter `p`. The
620+
* - `TSomeCall()` : Flow entered through a parameter. The
643621
* originating call does not improve the set of dispatch targets for any
644622
* method call in the current callable and was therefore not recorded.
645623
* - `TReturn(Callable c, DataFlowCall call)` : Flow reached `call` from `c` and
@@ -663,23 +641,21 @@ private module ImplCommon {
663641

664642
class CallContextSpecificCall extends CallContextCall, TSpecificCall {
665643
override string toString() {
666-
exists(DataFlowCall call, int i | this = TSpecificCall(call, i, _) |
667-
result = "CcCall(" + call + ", " + i + ")"
668-
)
644+
exists(DataFlowCall call | this = TSpecificCall(call) | result = "CcCall(" + call + ")")
669645
}
670646

671647
override predicate relevantFor(DataFlowCallable callable) {
672648
recordDataFlowCallSite(getCall(), callable)
673649
}
674650

675-
DataFlowCall getCall() { this = TSpecificCall(result, _, _) }
651+
DataFlowCall getCall() { this = TSpecificCall(result) }
676652
}
677653

678654
class CallContextSomeCall extends CallContextCall, TSomeCall {
679655
override string toString() { result = "CcSomeCall" }
680656

681657
override predicate relevantFor(DataFlowCallable callable) {
682-
exists(ParameterNode p | this = TSomeCall(p, _) and p.getEnclosingCallable() = callable)
658+
exists(ParameterNode p | p.getEnclosingCallable() = callable)
683659
}
684660
}
685661

@@ -848,7 +824,7 @@ private module ImplCommon {
848824

849825
bindingset[call, cc]
850826
DataFlowCallable resolveCall(DataFlowCall call, CallContext cc) {
851-
exists(DataFlowCall ctx | cc = TSpecificCall(ctx, _, _) |
827+
exists(DataFlowCall ctx | cc = TSpecificCall(ctx) |
852828
if reducedViableImplInCallContext(call, _, ctx)
853829
then result = prunedViableImplInCallContext(call, ctx)
854830
else result = viableCallable(call)
@@ -861,6 +837,76 @@ private module ImplCommon {
861837
result = viableCallable(call) and cc instanceof CallContextReturn
862838
}
863839

840+
newtype TSummary =
841+
TSummaryVal() or
842+
TSummaryTaint() or
843+
TSummaryReadVal(Content f) or
844+
TSummaryReadTaint(Content f) or
845+
TSummaryTaintStore(Content f)
846+
847+
/**
848+
* A summary of flow through a callable. This can either be value-preserving
849+
* if no additional steps are used, taint-flow if at least one additional step
850+
* is used, or any one of those combined with a store or a read. Summaries
851+
* recorded at a return node are restricted to include at least one additional
852+
* step, as the value-based summaries are calculated independent of the
853+
* configuration.
854+
*/
855+
class Summary extends TSummary {
856+
string toString() {
857+
result = "Val" and this = TSummaryVal()
858+
or
859+
result = "Taint" and this = TSummaryTaint()
860+
or
861+
exists(Content f |
862+
result = "ReadVal " + f.toString() and this = TSummaryReadVal(f)
863+
or
864+
result = "ReadTaint " + f.toString() and this = TSummaryReadTaint(f)
865+
or
866+
result = "TaintStore " + f.toString() and this = TSummaryTaintStore(f)
867+
)
868+
}
869+
870+
/** Gets the summary that results from extending this with an additional step. */
871+
Summary additionalStep() {
872+
this = TSummaryVal() and result = TSummaryTaint()
873+
or
874+
this = TSummaryTaint() and result = TSummaryTaint()
875+
or
876+
exists(Content f | this = TSummaryReadVal(f) and result = TSummaryReadTaint(f))
877+
or
878+
exists(Content f | this = TSummaryReadTaint(f) and result = TSummaryReadTaint(f))
879+
}
880+
881+
/** Gets the summary that results from extending this with a read. */
882+
Summary readStep(Content f) { this = TSummaryVal() and result = TSummaryReadVal(f) }
883+
884+
/** Gets the summary that results from extending this with a store. */
885+
Summary storeStep(Content f) { this = TSummaryTaint() and result = TSummaryTaintStore(f) }
886+
887+
/** Gets the summary that results from extending this with `step`. */
888+
bindingset[this, step]
889+
Summary compose(Summary step) {
890+
this = TSummaryVal() and result = step
891+
or
892+
this = TSummaryTaint() and
893+
(step = TSummaryTaint() or step = TSummaryTaintStore(_)) and
894+
result = step
895+
or
896+
exists(Content f |
897+
this = TSummaryReadVal(f) and step = TSummaryTaint() and result = TSummaryReadTaint(f)
898+
)
899+
or
900+
this = TSummaryReadTaint(_) and step = TSummaryTaint() and result = this
901+
}
902+
903+
/** Holds if this summary does not include any taint steps. */
904+
predicate isPartial() {
905+
this = TSummaryVal() or
906+
this = TSummaryReadVal(_)
907+
}
908+
}
909+
864910
pragma[noinline]
865911
DataFlowType getErasedNodeType(Node n) { result = getErasedRepr(n.getType()) }
866912

0 commit comments

Comments
 (0)