Skip to content

Commit 7eb6da3

Browse files
authored
Merge pull request github#5772 from smowton/smowton/feature/apache-tuple-flow
Add models for Apache Commons Lang's tuple types
2 parents 1ffd9c9 + d28c95d commit 7eb6da3

File tree

11 files changed

+1425
-0
lines changed

11 files changed

+1425
-0
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
lgtm,codescanning
2+
* Added models for the Apache Commons Lang tuple types (Pair, Triple and their immutable and mutable implementations). This may lead to more results from any query using data-flow analysis where a relevant path uses one of these container types.

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,22 @@ predicate summaryElement(DataFlowCallable c, string input, string output, string
7070
)
7171
}
7272

73+
private FieldContent parseField(string c) {
74+
External::specSplit(_, c, _) and
75+
exists(string fieldRegex, string package, string className, string fieldName |
76+
fieldRegex = "^Field\\[(.*)\\.([^.]+)\\.([^.]+)\\]$" and
77+
package = c.regexpCapture(fieldRegex, 1) and
78+
className = c.regexpCapture(fieldRegex, 2) and
79+
fieldName = c.regexpCapture(fieldRegex, 3) and
80+
result.getField().hasQualifiedName(package, className, fieldName)
81+
)
82+
}
83+
7384
/** Gets the summary component for specification component `c`, if any. */
7485
bindingset[c]
7586
SummaryComponent interpretComponentSpecific(string c) {
87+
result = SummaryComponent::content(parseField(c))
88+
or
7689
c = "ArrayElement" and result = SummaryComponent::content(any(ArrayContent c0))
7790
or
7891
c = "Element" and result = SummaryComponent::content(any(CollectionContent c0))

java/ql/src/semmle/code/java/frameworks/apache/Lang.qll

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,3 +789,72 @@ private class ApacheToStringBuilderModel extends SummaryModelCsv {
789789
]
790790
}
791791
}
792+
793+
/**
794+
* Value-propagating models for `Pair`, `ImmutablePair` and `MutablePair`.
795+
*/
796+
private class ApachePairModel extends SummaryModelCsv {
797+
override predicate row(string row) {
798+
row =
799+
[
800+
"org.apache.commons.lang3.tuple;Pair;false;getKey;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];ReturnValue;value",
801+
"org.apache.commons.lang3.tuple;Pair;false;getValue;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];ReturnValue;value",
802+
"org.apache.commons.lang3.tuple;Pair;false;getKey;;;Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];ReturnValue;value",
803+
"org.apache.commons.lang3.tuple;Pair;false;getValue;;;Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];ReturnValue;value",
804+
"org.apache.commons.lang3.tuple;Pair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value",
805+
"org.apache.commons.lang3.tuple;Pair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value",
806+
"org.apache.commons.lang3.tuple;ImmutablePair;false;ImmutablePair;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];value",
807+
"org.apache.commons.lang3.tuple;ImmutablePair;false;ImmutablePair;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];value",
808+
"org.apache.commons.lang3.tuple;ImmutablePair;false;getLeft;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];ReturnValue;value",
809+
"org.apache.commons.lang3.tuple;ImmutablePair;false;getRight;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];ReturnValue;value",
810+
"org.apache.commons.lang3.tuple;ImmutablePair;false;left;;;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value",
811+
"org.apache.commons.lang3.tuple;ImmutablePair;false;right;;;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value",
812+
"org.apache.commons.lang3.tuple;ImmutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value",
813+
"org.apache.commons.lang3.tuple;ImmutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value",
814+
"org.apache.commons.lang3.tuple;MutablePair;false;MutablePair;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];value",
815+
"org.apache.commons.lang3.tuple;MutablePair;false;MutablePair;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
816+
"org.apache.commons.lang3.tuple;MutablePair;false;getLeft;;;Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];ReturnValue;value",
817+
"org.apache.commons.lang3.tuple;MutablePair;false;getRight;;;Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];ReturnValue;value",
818+
"org.apache.commons.lang3.tuple;MutablePair;false;setLeft;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];value",
819+
"org.apache.commons.lang3.tuple;MutablePair;false;setRight;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
820+
"org.apache.commons.lang3.tuple;MutablePair;false;setValue;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
821+
"org.apache.commons.lang3.tuple;MutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of ReturnValue;value",
822+
"org.apache.commons.lang3.tuple;MutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutablePair.right] of ReturnValue;value"
823+
]
824+
}
825+
}
826+
827+
/**
828+
* Value-propagating models for `Triple`, `ImmutableTriple` and `MutableTriple`.
829+
*/
830+
private class ApacheTripleModel extends SummaryModelCsv {
831+
override predicate row(string row) {
832+
row =
833+
[
834+
"org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of ReturnValue;value",
835+
"org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of ReturnValue;value",
836+
"org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of ReturnValue;value",
837+
"org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of Argument[-1];value",
838+
"org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of Argument[-1];value",
839+
"org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of Argument[-1];value",
840+
"org.apache.commons.lang3.tuple;ImmutableTriple;false;getLeft;;;Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of Argument[-1];ReturnValue;value",
841+
"org.apache.commons.lang3.tuple;ImmutableTriple;false;getMiddle;;;Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of Argument[-1];ReturnValue;value",
842+
"org.apache.commons.lang3.tuple;ImmutableTriple;false;getRight;;;Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of Argument[-1];ReturnValue;value",
843+
"org.apache.commons.lang3.tuple;ImmutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of ReturnValue;value",
844+
"org.apache.commons.lang3.tuple;ImmutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of ReturnValue;value",
845+
"org.apache.commons.lang3.tuple;ImmutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of ReturnValue;value",
846+
"org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];value",
847+
"org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];value",
848+
"org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];value",
849+
"org.apache.commons.lang3.tuple;MutableTriple;false;getLeft;;;Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];ReturnValue;value",
850+
"org.apache.commons.lang3.tuple;MutableTriple;false;getMiddle;;;Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];ReturnValue;value",
851+
"org.apache.commons.lang3.tuple;MutableTriple;false;getRight;;;Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];ReturnValue;value",
852+
"org.apache.commons.lang3.tuple;MutableTriple;false;setLeft;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];value",
853+
"org.apache.commons.lang3.tuple;MutableTriple;false;setMiddle;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];value",
854+
"org.apache.commons.lang3.tuple;MutableTriple;false;setRight;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];value",
855+
"org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of ReturnValue;value",
856+
"org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of ReturnValue;value",
857+
"org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of ReturnValue;value"
858+
]
859+
}
860+
}
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
import org.apache.commons.lang3.tuple.Pair;
2+
import org.apache.commons.lang3.tuple.ImmutablePair;
3+
import org.apache.commons.lang3.tuple.MutablePair;
4+
5+
class PairTest {
6+
String taint() { return "tainted"; }
7+
8+
private static class IntSource {
9+
static int taint() { return 0; }
10+
}
11+
12+
void sink(Object o) {}
13+
14+
void test() throws Exception {
15+
16+
ImmutablePair<String, String> taintedLeft = ImmutablePair.of(taint(), "clean-right");
17+
ImmutablePair<String, String> taintedRight = ImmutablePair.of("clean-left", taint());
18+
Pair<String, String> taintedLeft2_ = ImmutablePair.left(taint());
19+
ImmutablePair<String, String> taintedLeft2 = (ImmutablePair)taintedLeft2_;
20+
Pair<String, String> taintedRight2_ = ImmutablePair.right(taint());
21+
ImmutablePair<String, String> taintedRight2 = (ImmutablePair)taintedRight2_;
22+
Pair<String, String> taintedLeft3 = Pair.of(taint(), "clean-right");
23+
Pair<String, String> taintedRight3 = Pair.of("clean-left", taint());
24+
ImmutablePair<String, String> taintedLeft4 = new ImmutablePair(taint(), "clean-right");
25+
ImmutablePair<String, String> taintedRight4 = new ImmutablePair("clean-left", taint());
26+
27+
// Check flow through ImmutablePairs:
28+
sink(taintedLeft.getLeft()); // $hasValueFlow
29+
sink(taintedLeft.getRight());
30+
sink(taintedLeft.getKey()); // $hasValueFlow
31+
sink(taintedLeft.getValue());
32+
sink(taintedLeft.left); // $hasValueFlow
33+
sink(taintedLeft.right);
34+
sink(taintedRight.getLeft());
35+
sink(taintedRight.getRight()); // $hasValueFlow
36+
sink(taintedRight.getKey());
37+
sink(taintedRight.getValue()); // $hasValueFlow
38+
sink(taintedRight.left);
39+
sink(taintedRight.right); // $hasValueFlow
40+
sink(taintedLeft2.getLeft()); // $hasValueFlow
41+
sink(taintedLeft2.getRight());
42+
sink(taintedLeft2.getKey()); // $hasValueFlow
43+
sink(taintedLeft2.getValue());
44+
sink(taintedLeft2.left); // $hasValueFlow
45+
sink(taintedLeft2.right);
46+
sink(taintedRight2.getLeft());
47+
sink(taintedRight2.getRight()); // $hasValueFlow
48+
sink(taintedRight2.getKey());
49+
sink(taintedRight2.getValue()); // $hasValueFlow
50+
sink(taintedRight2.left);
51+
sink(taintedRight2.right); // $hasValueFlow
52+
sink(taintedLeft3.getLeft()); // $hasValueFlow
53+
sink(taintedLeft3.getRight());
54+
sink(taintedLeft3.getKey()); // $hasValueFlow
55+
sink(taintedLeft3.getValue());
56+
sink(taintedRight3.getLeft());
57+
sink(taintedRight3.getRight()); // $hasValueFlow
58+
sink(taintedRight3.getKey());
59+
sink(taintedRight3.getValue()); // $hasValueFlow
60+
sink(taintedLeft4.getLeft()); // $hasValueFlow
61+
sink(taintedLeft4.getRight());
62+
sink(taintedLeft4.getKey()); // $hasValueFlow
63+
sink(taintedLeft4.getValue());
64+
sink(taintedLeft4.left); // $hasValueFlow
65+
sink(taintedLeft4.right);
66+
sink(taintedRight4.getLeft());
67+
sink(taintedRight4.getRight()); // $hasValueFlow
68+
sink(taintedRight4.getKey());
69+
sink(taintedRight4.getValue()); // $hasValueFlow
70+
sink(taintedRight4.left);
71+
sink(taintedRight4.right); // $hasValueFlow
72+
73+
// Check flow also works via an alias of type Pair:
74+
sink(taintedLeft2_.getLeft()); // $hasValueFlow
75+
sink(taintedLeft2_.getRight());
76+
sink(taintedLeft2_.getKey()); // $hasValueFlow
77+
sink(taintedLeft2_.getValue());
78+
sink(taintedRight2_.getLeft());
79+
sink(taintedRight2_.getRight()); // $hasValueFlow
80+
sink(taintedRight2_.getKey());
81+
sink(taintedRight2_.getValue()); // $hasValueFlow
82+
83+
// Check flow through MutablePairs:
84+
MutablePair<String, String> taintedLeftMutable = MutablePair.of(taint(), "clean-right");
85+
MutablePair<String, String> taintedRightMutable = MutablePair.of("clean-left", taint());
86+
MutablePair<String, String> setTaintLeft = MutablePair.of("clean-left", "clean-right");
87+
setTaintLeft.setLeft(taint());
88+
MutablePair<String, String> setTaintRight = MutablePair.of("clean-left", "clean-right");
89+
setTaintRight.setRight(taint());
90+
MutablePair<String, String> setTaintValue = MutablePair.of("clean-left", "clean-right");
91+
setTaintValue.setValue(taint());
92+
MutablePair<String, String> taintedLeftMutableConstructed = new MutablePair(taint(), "clean-right");
93+
MutablePair<String, String> taintedRightMutableConstructed = new MutablePair("clean-left", taint());
94+
95+
sink(taintedLeftMutable.getLeft()); // $hasValueFlow
96+
sink(taintedLeftMutable.getRight());
97+
sink(taintedLeftMutable.getKey()); // $hasValueFlow
98+
sink(taintedLeftMutable.getValue());
99+
sink(taintedLeftMutable.left); // $hasValueFlow
100+
sink(taintedLeftMutable.right);
101+
sink(taintedRightMutable.getLeft());
102+
sink(taintedRightMutable.getRight()); // $hasValueFlow
103+
sink(taintedRightMutable.getKey());
104+
sink(taintedRightMutable.getValue()); // $hasValueFlow
105+
sink(taintedRightMutable.left);
106+
sink(taintedRightMutable.right); // $hasValueFlow
107+
sink(setTaintLeft.getLeft()); // $hasValueFlow
108+
sink(setTaintLeft.getRight());
109+
sink(setTaintLeft.getKey()); // $hasValueFlow
110+
sink(setTaintLeft.getValue());
111+
sink(setTaintLeft.left); // $hasValueFlow
112+
sink(setTaintLeft.right);
113+
sink(setTaintRight.getLeft());
114+
sink(setTaintRight.getRight()); // $hasValueFlow
115+
sink(setTaintRight.getKey());
116+
sink(setTaintRight.getValue()); // $hasValueFlow
117+
sink(setTaintRight.left);
118+
sink(setTaintRight.right); // $hasValueFlow
119+
sink(setTaintValue.getLeft());
120+
sink(setTaintValue.getRight()); // $hasValueFlow
121+
sink(setTaintValue.getKey());
122+
sink(setTaintValue.getValue()); // $hasValueFlow
123+
sink(setTaintValue.left);
124+
sink(setTaintValue.right); // $hasValueFlow
125+
sink(taintedLeftMutableConstructed.getLeft()); // $hasValueFlow
126+
sink(taintedLeftMutableConstructed.getRight());
127+
sink(taintedLeftMutableConstructed.getKey()); // $hasValueFlow
128+
sink(taintedLeftMutableConstructed.getValue());
129+
sink(taintedLeftMutableConstructed.left); // $hasValueFlow
130+
sink(taintedLeftMutableConstructed.right);
131+
sink(taintedRightMutableConstructed.getLeft());
132+
sink(taintedRightMutableConstructed.getRight()); // $hasValueFlow
133+
sink(taintedRightMutableConstructed.getKey());
134+
sink(taintedRightMutableConstructed.getValue()); // $hasValueFlow
135+
sink(taintedRightMutableConstructed.left);
136+
sink(taintedRightMutableConstructed.right); // $hasValueFlow
137+
138+
// Check flow also works via an alias of type Pair:
139+
Pair<String, String> taintedLeftMutableAlias = taintedLeftMutable;
140+
Pair<String, String> taintedRightMutableAlias = taintedRightMutable;
141+
sink(taintedLeftMutableAlias.getLeft()); // $hasValueFlow
142+
sink(taintedLeftMutableAlias.getRight());
143+
sink(taintedLeftMutableAlias.getKey()); // $hasValueFlow
144+
sink(taintedLeftMutableAlias.getValue());
145+
sink(taintedRightMutableAlias.getLeft());
146+
sink(taintedRightMutableAlias.getRight()); // $hasValueFlow
147+
sink(taintedRightMutableAlias.getKey());
148+
sink(taintedRightMutableAlias.getValue()); // $hasValueFlow
149+
}
150+
}

0 commit comments

Comments
 (0)