Skip to content

Commit 3024b5c

Browse files
committed
Java: Bugfix for flow through methods with taintstep and upcast.
1 parent 12c906c commit 3024b5c

File tree

4 files changed

+82
-15
lines changed

4 files changed

+82
-15
lines changed

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

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -851,8 +851,6 @@ private class AccessPathFrontNilNode extends Node {
851851
localFlowBigStep(_, this, false, _)
852852
or
853853
additionalJumpStep(_, this, _)
854-
or
855-
simpleArgumentFlowsThrough(_, this, _, _)
856854
)
857855
}
858856

@@ -914,10 +912,10 @@ private predicate flowCandFwd0(Node node, boolean fromArg, AccessPathFront apf,
914912
argumentValueFlowsThrough(mid, node, _)
915913
)
916914
or
917-
exists(Node mid, AccessPathFrontNil nil |
915+
exists(Node mid, AccessPathFrontNil nil, DataFlowType t |
918916
flowCandFwd(mid, fromArg, nil, config) and
919-
simpleArgumentFlowsThrough(mid, node, _, config) and
920-
apf = node.(AccessPathFrontNilNode).getApf()
917+
simpleArgumentFlowsThrough(mid, node, t, config) and
918+
apf = TFrontNil(t)
921919
)
922920
)
923921
or
@@ -1187,10 +1185,10 @@ private predicate flowFwd0(
11871185
argumentValueFlowsThrough(mid, node, _)
11881186
)
11891187
or
1190-
exists(Node mid, AccessPathNil nil |
1188+
exists(Node mid, AccessPathNil nil, DataFlowType t |
11911189
flowFwd(mid, fromArg, _, nil, config) and
1192-
simpleArgumentFlowsThrough(mid, node, _, config) and
1193-
ap = node.(AccessPathNilNode).getAp() and
1190+
simpleArgumentFlowsThrough(mid, node, t, config) and
1191+
ap = TNil(t) and
11941192
apf = ap.(AccessPathNil).getFront()
11951193
)
11961194
)
@@ -1539,7 +1537,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, AccessPat
15391537
or
15401538
pathOutOfCallable(mid, node, cc) and ap = mid.getAp()
15411539
or
1542-
pathThroughCallable(mid, node, cc) and ap = node.(AccessPathNilNode).getAp()
1540+
pathThroughCallable(mid, node, cc, ap)
15431541
or
15441542
valuePathThroughCallable(mid, node, cc) and ap = mid.getAp()
15451543
}
@@ -1670,14 +1668,14 @@ private predicate pathIntoCallable(
16701668
/** Holds if data may flow from `p` to a return of kind `kind`. */
16711669
pragma[nomagic]
16721670
private predicate paramFlowsThrough(
1673-
ParameterNode p, ReturnKind kind, CallContextCall cc, Configuration config
1671+
ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config
16741672
) {
16751673
exists(PathNodeMid mid, ReturnNode ret |
16761674
mid.getNode() = ret and
16771675
kind = ret.getKind() and
16781676
cc = mid.getCallContext() and
16791677
config = mid.getConfiguration() and
1680-
mid.getAp() instanceof AccessPathNil
1678+
apnil = mid.getAp()
16811679
|
16821680
cc = TSomeCall(p, true)
16831681
or
@@ -1689,11 +1687,11 @@ private predicate paramFlowsThrough(
16891687

16901688
pragma[noinline]
16911689
private predicate pathThroughCallable0(
1692-
DataFlowCall call, PathNodeMid mid, ReturnKind kind, CallContext cc
1690+
DataFlowCall call, PathNodeMid mid, ReturnKind kind, CallContext cc, AccessPathNil apnil
16931691
) {
16941692
exists(ParameterNode p, CallContext innercc |
16951693
pathIntoCallable(mid, p, cc, innercc, call) and
1696-
paramFlowsThrough(p, kind, innercc, unbind(mid.getConfiguration())) and
1694+
paramFlowsThrough(p, kind, innercc, apnil, unbind(mid.getConfiguration())) and
16971695
not parameterValueFlowsThrough(p, kind, innercc) and
16981696
mid.getAp() instanceof AccessPathNil
16991697
)
@@ -1704,9 +1702,11 @@ private predicate pathThroughCallable0(
17041702
* The context `cc` is restored to its value prior to entering the callable.
17051703
*/
17061704
pragma[noinline]
1707-
private predicate pathThroughCallable(PathNodeMid mid, OutNode out, CallContext cc) {
1705+
private predicate pathThroughCallable(
1706+
PathNodeMid mid, OutNode out, CallContext cc, AccessPathNil apnil
1707+
) {
17081708
exists(DataFlowCall call, ReturnKind kind |
1709-
pathThroughCallable0(call, mid, kind, cc) and
1709+
pathThroughCallable0(call, mid, kind, cc, apnil) and
17101710
out = getAnOutNode(call, kind)
17111711
)
17121712
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
public class Test {
2+
static class A {
3+
B step() { return null; }
4+
}
5+
static class B extends C { }
6+
static class C { }
7+
8+
A src() { return new A(); }
9+
10+
void sink(Object o) { }
11+
12+
void flow() {
13+
A a = src();
14+
C c = m1(a);
15+
sink(c);
16+
}
17+
18+
C m1(A a) {
19+
return a.step();
20+
}
21+
}
22+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
| 1 | 1 |
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import java
2+
import semmle.code.java.dataflow.TaintTracking
3+
import DataFlow
4+
5+
predicate step(Expr e1, Expr e2) {
6+
exists(MethodAccess ma |
7+
ma.getMethod().hasName("step") and
8+
ma = e2 and
9+
ma.getQualifier() = e1
10+
)
11+
}
12+
13+
predicate isSink0(Expr sink) {
14+
exists(MethodAccess ma |
15+
ma.getMethod().hasName("sink") and
16+
ma.getAnArgument() = sink
17+
)
18+
}
19+
20+
class Conf1 extends Configuration {
21+
Conf1() { this = "testconf1" }
22+
23+
override predicate isSource(Node n) { n.asExpr().(MethodAccess).getMethod().hasName("src") }
24+
25+
override predicate isSink(Node n) { any() }
26+
27+
override predicate isAdditionalFlowStep(Node n1, Node n2) { step(n1.asExpr(), n2.asExpr()) }
28+
}
29+
30+
class Conf2 extends Configuration {
31+
Conf2() { this = "testconf2" }
32+
33+
override predicate isSource(Node n) { n.asExpr().(MethodAccess).getMethod().hasName("src") }
34+
35+
override predicate isSink(Node n) { isSink0(n.asExpr()) }
36+
37+
override predicate isAdditionalFlowStep(Node n1, Node n2) { step(n1.asExpr(), n2.asExpr()) }
38+
}
39+
40+
from int i1, int i2
41+
where
42+
i1 = count(Node src, Node sink, Conf1 c | c.hasFlow(src, sink) and isSink0(sink.asExpr())) and
43+
i2 = count(Node src, Node sink, Conf2 c | c.hasFlow(src, sink))
44+
select i1, i2

0 commit comments

Comments
 (0)