Skip to content

Commit d69ecde

Browse files
Java: Add additional flow steps for guava collection methods and more unit tests
1 parent 7e11d8e commit d69ecde

File tree

20 files changed

+1729
-83
lines changed

20 files changed

+1729
-83
lines changed

java/ql/src/semmle/code/java/frameworks/guava/Collections.qll

Lines changed: 118 additions & 64 deletions
Large diffs are not rendered by default.
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
package com.google.common.collect;
2+
3+
import java.util.Map;
4+
import java.util.SortedSet;
5+
import java.util.SortedMap;
6+
import java.util.Comparator;
7+
8+
class TestCollect {
9+
String taint() { return "tainted"; }
10+
11+
void sink(Object o) {}
12+
13+
void test1() {
14+
String x = taint();
15+
16+
ImmutableSet<String> xs = ImmutableSet.of(x, "y", "z");
17+
sink(xs.asList());
18+
19+
ImmutableSet<String> ys = ImmutableSet.of("a", "b", "c");
20+
21+
sink(Sets.filter(Sets.union(xs, ys), y -> true));
22+
23+
sink(Sets.newHashSet("a", "b", "c", "d", x));
24+
}
25+
26+
void test2() {
27+
sink(ImmutableList.of(taint(), taint(), taint(), taint())); // expect 4 alerts
28+
sink(ImmutableMap.of(taint(), taint(), taint(), taint())); // expect 2 alerts
29+
sink(ImmutableMultimap.of(taint(), taint(), taint(), taint())); // expect 2 alerts
30+
sink(ImmutableTable.of(taint(),taint(), taint())); // expect 1 alert
31+
}
32+
33+
void test3() {
34+
String x = taint();
35+
36+
ImmutableList.Builder<String> b = ImmutableList.builder();
37+
38+
b.add("a");
39+
sink(b);
40+
b.add(x);
41+
sink(b.build());
42+
43+
b = ImmutableList.builder();
44+
45+
b.add("a").add(x);
46+
sink(b.build());
47+
48+
sink(ImmutableList.builder().add("a").add(x).build());
49+
50+
ImmutableMap.Builder<String, String> b2 = ImmutableMap.builder();
51+
b2.put(x,"v");
52+
sink(b2);
53+
b2.put("k",x);
54+
sink(b2.build());
55+
}
56+
57+
void test4(Table<String, String, String> t1, Table<String, String, String> t2, Table<String, String, String> t3) {
58+
String x = taint();
59+
t1.put(x, "c", "v");
60+
sink(t1);
61+
t1.put("r", x, "v");
62+
sink(t1);
63+
t1.put("r", "c", x);
64+
sink(t1);
65+
sink(t1.row("r"));
66+
67+
t2.putAll(t1);
68+
for (Table.Cell<String,String,String> c : t2.cellSet()) {
69+
sink(c.getValue());
70+
}
71+
72+
sink(t1.remove("r", "c"));
73+
74+
t3.row("r").put("c", x);
75+
sink(t3); // Not detected
76+
}
77+
78+
void test4(Multimap<String, String> m1, Multimap<String, String> m2, Multimap<String, String> m3,
79+
Multimap<String, String> m4, Multimap<String, String> m5){
80+
String x = taint();
81+
m1.put("k", x);
82+
sink(m1);
83+
sink(m1.get("k"));
84+
85+
m2.putAll("k", ImmutableList.of("a", x, "b"));
86+
sink(m2);
87+
88+
m3.putAll(m1);
89+
sink(m3);
90+
91+
m4.replaceValues("k", m1.replaceValues("k", ImmutableList.of("a")));
92+
for (Map.Entry<String, String> e : m4.entries()) {
93+
sink(e.getValue());
94+
}
95+
96+
m5.asMap().get("k").add(x);
97+
sink(m5); // Not detected
98+
}
99+
100+
void test5(Comparator<String> comp, SortedSet<String> sorS, SortedMap<String, String> sorM) {
101+
ImmutableSortedSet<String> s = ImmutableSortedSet.of(taint());
102+
103+
sink(s);
104+
sink(ImmutableSortedSet.copyOf(s));
105+
sink(ImmutableSortedSet.copyOf(comp, s));
106+
107+
sorS.add(taint());
108+
sink(ImmutableSortedSet.copyOfSorted(sorS));
109+
110+
sink(ImmutableList.sortedCopyOf(s));
111+
sink(ImmutableList.sortedCopyOf(comp, s));
112+
113+
ImmutableSortedMap<String, String> m = ImmutableSortedMap.of("k", taint());
114+
115+
sink(m);
116+
sink(ImmutableSortedMap.copyOf(m));
117+
sink(ImmutableSortedMap.copyOf(m, comp));
118+
119+
sorM.put("k", taint());
120+
sink(ImmutableSortedMap.copyOfSorted(sorM));
121+
}
122+
}

java/ql/test/library-tests/frameworks/guava/Test.java renamed to java/ql/test/library-tests/frameworks/guava/TestStrings.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import java.util.Map;
77
import java.util.HashMap;
88

9-
class Test {
9+
class TestStrings {
1010
String taint() { return "tainted"; }
1111

1212
void sink(Object o) {}
Lines changed: 52 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,52 @@
1-
| Test.java:15:20:15:26 | taint(...) | Test.java:17:14:17:41 | padStart(...) |
2-
| Test.java:15:20:15:26 | taint(...) | Test.java:18:14:18:39 | padEnd(...) |
3-
| Test.java:15:20:15:26 | taint(...) | Test.java:19:14:19:33 | repeat(...) |
4-
| Test.java:15:20:15:26 | taint(...) | Test.java:20:14:20:56 | emptyToNull(...) |
5-
| Test.java:15:20:15:26 | taint(...) | Test.java:21:14:21:40 | lenientFormat(...) |
6-
| Test.java:15:20:15:26 | taint(...) | Test.java:24:14:24:51 | lenientFormat(...) |
7-
| Test.java:28:20:28:26 | taint(...) | Test.java:32:14:32:23 | split(...) |
8-
| Test.java:28:20:28:26 | taint(...) | Test.java:33:14:33:29 | splitToList(...) |
9-
| Test.java:28:20:28:26 | taint(...) | Test.java:35:14:35:50 | split(...) |
10-
| Test.java:39:20:39:26 | taint(...) | Test.java:46:14:46:54 | appendTo(...) |
11-
| Test.java:39:20:39:26 | taint(...) | Test.java:47:14:47:26 | toString(...) |
12-
| Test.java:39:20:39:26 | taint(...) | Test.java:48:14:48:51 | appendTo(...) |
13-
| Test.java:39:20:39:26 | taint(...) | Test.java:49:14:49:26 | toString(...) |
14-
| Test.java:39:20:39:26 | taint(...) | Test.java:52:14:52:42 | appendTo(...) |
15-
| Test.java:39:20:39:26 | taint(...) | Test.java:57:14:57:56 | join(...) |
16-
| Test.java:39:20:39:26 | taint(...) | Test.java:58:14:58:82 | join(...) |
17-
| Test.java:39:20:39:26 | taint(...) | Test.java:60:14:60:58 | join(...) |
1+
| TestCollect.java:14:20:14:26 | taint(...) | TestCollect.java:17:14:17:24 | asList(...) |
2+
| TestCollect.java:14:20:14:26 | taint(...) | TestCollect.java:21:14:21:55 | filter(...) |
3+
| TestCollect.java:14:20:14:26 | taint(...) | TestCollect.java:23:14:23:51 | newHashSet(...) |
4+
| TestCollect.java:27:31:27:37 | taint(...) | TestCollect.java:27:14:27:65 | of(...) |
5+
| TestCollect.java:27:40:27:46 | taint(...) | TestCollect.java:27:14:27:65 | of(...) |
6+
| TestCollect.java:27:49:27:55 | taint(...) | TestCollect.java:27:14:27:65 | of(...) |
7+
| TestCollect.java:27:58:27:64 | taint(...) | TestCollect.java:27:14:27:65 | of(...) |
8+
| TestCollect.java:28:39:28:45 | taint(...) | TestCollect.java:28:14:28:64 | of(...) |
9+
| TestCollect.java:28:57:28:63 | taint(...) | TestCollect.java:28:14:28:64 | of(...) |
10+
| TestCollect.java:29:44:29:50 | taint(...) | TestCollect.java:29:14:29:69 | of(...) |
11+
| TestCollect.java:29:62:29:68 | taint(...) | TestCollect.java:29:14:29:69 | of(...) |
12+
| TestCollect.java:30:49:30:55 | taint(...) | TestCollect.java:30:14:30:56 | of(...) |
13+
| TestCollect.java:34:20:34:26 | taint(...) | TestCollect.java:41:14:41:22 | build(...) |
14+
| TestCollect.java:34:20:34:26 | taint(...) | TestCollect.java:46:14:46:22 | build(...) |
15+
| TestCollect.java:34:20:34:26 | taint(...) | TestCollect.java:48:14:48:60 | build(...) |
16+
| TestCollect.java:34:20:34:26 | taint(...) | TestCollect.java:54:14:54:23 | build(...) |
17+
| TestCollect.java:58:20:58:26 | taint(...) | TestCollect.java:64:14:64:15 | t1 |
18+
| TestCollect.java:58:20:58:26 | taint(...) | TestCollect.java:65:14:65:24 | row(...) |
19+
| TestCollect.java:58:20:58:26 | taint(...) | TestCollect.java:69:18:69:29 | getValue(...) |
20+
| TestCollect.java:58:20:58:26 | taint(...) | TestCollect.java:72:14:72:32 | remove(...) |
21+
| TestCollect.java:80:20:80:26 | taint(...) | TestCollect.java:82:14:82:15 | m1 |
22+
| TestCollect.java:80:20:80:26 | taint(...) | TestCollect.java:83:14:83:24 | get(...) |
23+
| TestCollect.java:80:20:80:26 | taint(...) | TestCollect.java:86:14:86:15 | m2 |
24+
| TestCollect.java:80:20:80:26 | taint(...) | TestCollect.java:89:14:89:15 | m3 |
25+
| TestCollect.java:80:20:80:26 | taint(...) | TestCollect.java:93:18:93:29 | getValue(...) |
26+
| TestCollect.java:101:62:101:68 | taint(...) | TestCollect.java:103:14:103:14 | s |
27+
| TestCollect.java:101:62:101:68 | taint(...) | TestCollect.java:104:14:104:41 | copyOf(...) |
28+
| TestCollect.java:101:62:101:68 | taint(...) | TestCollect.java:105:14:105:47 | copyOf(...) |
29+
| TestCollect.java:101:62:101:68 | taint(...) | TestCollect.java:110:14:110:42 | sortedCopyOf(...) |
30+
| TestCollect.java:101:62:101:68 | taint(...) | TestCollect.java:111:14:111:48 | sortedCopyOf(...) |
31+
| TestCollect.java:107:18:107:24 | taint(...) | TestCollect.java:108:14:108:50 | copyOfSorted(...) |
32+
| TestCollect.java:113:75:113:81 | taint(...) | TestCollect.java:115:14:115:14 | m |
33+
| TestCollect.java:113:75:113:81 | taint(...) | TestCollect.java:116:14:116:41 | copyOf(...) |
34+
| TestCollect.java:113:75:113:81 | taint(...) | TestCollect.java:117:14:117:47 | copyOf(...) |
35+
| TestCollect.java:119:23:119:29 | taint(...) | TestCollect.java:120:14:120:50 | copyOfSorted(...) |
36+
| TestStrings.java:15:20:15:26 | taint(...) | TestStrings.java:17:14:17:41 | padStart(...) |
37+
| TestStrings.java:15:20:15:26 | taint(...) | TestStrings.java:18:14:18:39 | padEnd(...) |
38+
| TestStrings.java:15:20:15:26 | taint(...) | TestStrings.java:19:14:19:33 | repeat(...) |
39+
| TestStrings.java:15:20:15:26 | taint(...) | TestStrings.java:20:14:20:56 | emptyToNull(...) |
40+
| TestStrings.java:15:20:15:26 | taint(...) | TestStrings.java:21:14:21:40 | lenientFormat(...) |
41+
| TestStrings.java:15:20:15:26 | taint(...) | TestStrings.java:24:14:24:51 | lenientFormat(...) |
42+
| TestStrings.java:28:20:28:26 | taint(...) | TestStrings.java:32:14:32:23 | split(...) |
43+
| TestStrings.java:28:20:28:26 | taint(...) | TestStrings.java:33:14:33:29 | splitToList(...) |
44+
| TestStrings.java:28:20:28:26 | taint(...) | TestStrings.java:35:14:35:50 | split(...) |
45+
| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:46:14:46:54 | appendTo(...) |
46+
| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:47:14:47:26 | toString(...) |
47+
| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:48:14:48:51 | appendTo(...) |
48+
| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:49:14:49:26 | toString(...) |
49+
| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:52:14:52:42 | appendTo(...) |
50+
| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:57:14:57:56 | join(...) |
51+
| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:58:14:58:82 | join(...) |
52+
| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:60:14:60:58 | join(...) |

java/ql/test/stubs/guava-30.0/com/google/common/base/Splitter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public static Splitter on(final String separator) {
2525
}
2626

2727
public Splitter omitEmptyStrings() {
28-
return null;;
28+
return null;
2929
}
3030

3131
public Iterable<String> split(final CharSequence sequence) {
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Copyright (C) 2012 The Guava Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.common.collect;
18+
19+
import java.util.Collection;
20+
import java.util.Map;
21+
import java.util.Map.Entry;
22+
import java.util.Set;
23+
24+
abstract class AbstractMultimap<K, V> implements Multimap<K, V> {
25+
@Override
26+
public boolean isEmpty() {
27+
return false;
28+
}
29+
30+
@Override
31+
public boolean containsValue(Object value) {
32+
return false;
33+
}
34+
35+
@Override
36+
public boolean containsEntry(Object key, Object value) {
37+
return false;
38+
}
39+
40+
@Override
41+
public boolean remove(Object key, Object value) {
42+
return false;
43+
}
44+
45+
@Override
46+
public boolean put(K key, V value) {
47+
return false;
48+
}
49+
50+
@Override
51+
public boolean putAll(K key, Iterable<? extends V> values) {
52+
return false;
53+
}
54+
55+
@Override
56+
public boolean putAll(Multimap<? extends K, ? extends V> multimap) {
57+
return false;
58+
}
59+
60+
@Override
61+
public Collection<V> replaceValues(K key, Iterable<? extends V> values) {
62+
return null;
63+
}
64+
65+
@Override
66+
public Collection<Entry<K, V>> entries() {
67+
return null;
68+
}
69+
70+
@Override
71+
public Set<K> keySet() {
72+
return null;
73+
}
74+
75+
@Override
76+
public Multiset<K> keys() {
77+
return null;
78+
}
79+
80+
@Override
81+
public Collection<V> values() {
82+
return null;
83+
}
84+
85+
@Override
86+
public Map<K, Collection<V>> asMap() {
87+
return null;
88+
}
89+
90+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Copyright (C) 2013 The Guava Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5+
* in compliance with the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License
10+
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11+
* or implied. See the License for the specific language governing permissions and limitations under
12+
* the License.
13+
*/
14+
15+
package com.google.common.collect;
16+
17+
import java.util.Collection;
18+
import java.util.Map;
19+
import java.util.Set;
20+
21+
abstract class AbstractTable<R, C, V> implements Table<R, C, V> {
22+
@Override
23+
public boolean containsRow(Object rowKey) {
24+
return false;
25+
}
26+
27+
@Override
28+
public boolean containsColumn(Object columnKey) {
29+
return false;
30+
}
31+
32+
@Override
33+
public Set<R> rowKeySet() {
34+
return null;
35+
}
36+
37+
@Override
38+
public Set<C> columnKeySet() {
39+
return null;
40+
}
41+
42+
@Override
43+
public boolean containsValue(Object value) {
44+
return false;
45+
}
46+
47+
@Override
48+
public boolean contains(Object rowKey, Object columnKey) {
49+
return false;
50+
}
51+
52+
@Override
53+
public V get(Object rowKey, Object columnKey) {
54+
return null;
55+
}
56+
57+
@Override
58+
public boolean isEmpty() {
59+
return false;
60+
}
61+
62+
@Override
63+
public void clear() {
64+
}
65+
66+
@Override
67+
public V remove(Object rowKey, Object columnKey) {
68+
return null;
69+
}
70+
71+
@Override
72+
public V put(R rowKey, C columnKey, V value) {
73+
return null;
74+
}
75+
76+
@Override
77+
public void putAll(Table<? extends R, ? extends C, ? extends V> table) {
78+
}
79+
80+
@Override
81+
public Set<Cell<R, C, V>> cellSet() {
82+
return null;
83+
}
84+
85+
@Override
86+
public Collection<V> values() {
87+
return null;
88+
}
89+
90+
}

0 commit comments

Comments
 (0)