Skip to content

Commit 7a4ce83

Browse files
Merge pull request github#5310 from joefarebrother/guava-io
Java: Add modelling for Guava IO utilities
2 parents 2a9f7a9 + bd4a414 commit 7a4ce83

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1927
-106
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
lgtm,codescanning
2+
* Increased coverage of the Guava framework by including classes in the `com.google.common.io` package.

java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.ql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import java
99
import semmle.code.java.dataflow.TaintTracking
1010
import semmle.code.java.dataflow.FlowSources
11+
import semmle.code.java.dataflow.ExternalFlow
1112
import DataFlow::PathGraph
1213

1314
class URLConstructor extends ClassInstanceExpr {
@@ -37,6 +38,8 @@ class RemoteURLToOpenStreamFlowConfig extends TaintTracking::Configuration {
3738
exists(MethodAccess m |
3839
sink.asExpr() = m.getQualifier() and m.getMethod() instanceof URLOpenStreamMethod
3940
)
41+
or
42+
sinkNode(sink, "url-open-stream")
4043
}
4144

4245
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ private import internal.DataFlowPrivate
7171
private module Frameworks {
7272
private import semmle.code.java.frameworks.ApacheHttp
7373
private import semmle.code.java.frameworks.apache.Lang
74+
private import semmle.code.java.frameworks.guava.Guava
7475
}
7576

7677
private predicate sourceModelCsv(string row) {

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ import java
66
import StringUtils
77
import Collections
88
import Preconditions
9+
import IO
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/** Definitions of taint steps in the IO package of the Guava framework */
2+
3+
import java
4+
private import semmle.code.java.dataflow.ExternalFlow
5+
6+
private class GuavaIoCsv extends SummaryModelCsv {
7+
override predicate row(string row) {
8+
row =
9+
[
10+
//"package;type;overrides;name;signature;ext;inputspec;outputspec;kind",
11+
"com.google.common.io;BaseEncoding;true;decode;(CharSequence);;Argument[0];ReturnValue;taint",
12+
"com.google.common.io;BaseEncoding;true;decodingStream;(Reader);;Argument[0];ReturnValue;taint",
13+
"com.google.common.io;BaseEncoding;true;decodingSource;(CharSource);;Argument[0];ReturnValue;taint",
14+
"com.google.common.io;BaseEncoding;true;encode;(byte[]);;Argument[0];ReturnValue;taint",
15+
"com.google.common.io;BaseEncoding;true;encode;(byte[],int,int);;Argument[0];ReturnValue;taint",
16+
"com.google.common.io;BaseEncoding;true;withSeparator;(String,int);;Argument[0];ReturnValue;taint",
17+
"com.google.common.io;BaseEncoding;true;decode;(CharSequence);;Argument[-1];ReturnValue;taint",
18+
"com.google.common.io;BaseEncoding;true;decodingStream;(Reader);;Argument[-1];ReturnValue;taint",
19+
"com.google.common.io;BaseEncoding;true;decodingSource;(CharSource);;Argument[-1];ReturnValue;taint",
20+
"com.google.common.io;BaseEncoding;true;encode;(byte[]);;Argument[-1];ReturnValue;taint",
21+
"com.google.common.io;BaseEncoding;true;upperCase;();;Argument[-1];ReturnValue;taint",
22+
"com.google.common.io;BaseEncoding;true;lowerCase;();;Argument[-1];ReturnValue;taint",
23+
"com.google.common.io;BaseEncoding;true;withPadChar;(char);;Argument[-1];ReturnValue;taint",
24+
"com.google.common.io;BaseEncoding;true;omitPadding;();;Argument[-1];ReturnValue;taint",
25+
"com.google.common.io;BaseEncoding;true;encode;(byte[],int,int);;Argument[-1];ReturnValue;taint",
26+
"com.google.common.io;ByteSource;true;asCharSource;(Charset);;Argument[-1];ReturnValue;taint",
27+
"com.google.common.io;ByteSource;true;concat;;;Argument[0];ReturnValue;taint",
28+
"com.google.common.io;ByteSource;true;copyTo;(OutputStream);;Argument[-1];Argument[0];taint",
29+
"com.google.common.io;ByteSource;true;openStream;();;Argument[-1];ReturnValue;taint",
30+
"com.google.common.io;ByteSource;true;openBufferedStream;();;Argument[-1];ReturnValue;taint",
31+
"com.google.common.io;ByteSource;true;read;();;Argument[-1];ReturnValue;taint",
32+
"com.google.common.io;ByteSource;true;slice;(long,long);;Argument[-1];ReturnValue;taint",
33+
"com.google.common.io;ByteSource;true;wrap;(byte[]);;Argument[0];ReturnValue;taint",
34+
"com.google.common.io;ByteStreams;false;copy;(InputStream,OutputStream);;Argument[0];Argument[1];taint",
35+
"com.google.common.io;ByteStreams;false;copy;(ReadablyByteChannel,WritableByteChannel);;Argument[0];Argument[1];taint",
36+
"com.google.common.io;ByteStreams;false;limit;(InputStream,long);;Argument[0];ReturnValue;taint",
37+
"com.google.common.io;ByteStreams;false;newDataInput;(byte[]);;Argument[0];ReturnValue;taint",
38+
"com.google.common.io;ByteStreams;false;newDataInput;(byte[],int);;Argument[0];ReturnValue;taint",
39+
"com.google.common.io;ByteStreams;false;newDataInput;(ByteArrayInputStream);;Argument[0];ReturnValue;taint",
40+
"com.google.common.io;ByteStreams;false;newDataOutput;(ByteArrayOutputStream);;Argument[0];ReturnValue;taint",
41+
"com.google.common.io;ByteStreams;false;read;(InputStream,byte[],int,int);;Argument[0];Argument[1];taint",
42+
"com.google.common.io;ByteStreams;false;readFully;(InputStream,byte[]);;Argument[0];Argument[1];taint",
43+
"com.google.common.io;ByteStreams;false;readFully;(InputStream,byte[],int,int);;Argument[0];Argument[1];taint",
44+
"com.google.common.io;ByteStreams;false;toByteArray;(InputStream);;Argument[0];ReturnValue;taint",
45+
"com.google.common.io;CharSource;true;asByteSource;(Charset);;Argument[-1];ReturnValue;taint",
46+
"com.google.common.io;CharSource;true;concat;;;Argument[0];ReturnValue;taint",
47+
"com.google.common.io;CharSource;true;copyTo;(Appendable);;Argument[-1];Argument[0];taint",
48+
"com.google.common.io;CharSource;true;openStream;();;Argument[-1];ReturnValue;taint",
49+
"com.google.common.io;CharSource;true;openBufferedStream;();;Argument[-1];ReturnValue;taint",
50+
"com.google.common.io;CharSource;true;read;();;Argument[-1];ReturnValue;taint",
51+
"com.google.common.io;CharSource;true;readFirstLine;();;Argument[-1];ReturnValue;taint",
52+
"com.google.common.io;CharSource;true;readLines;();;Argument[-1];ReturnValue;taint",
53+
"com.google.common.io;CharSource;true;lines;();;Argument[-1];ReturnValue;taint",
54+
"com.google.common.io;CharSource;true;wrap;(CharSequence);;Argument[0];ReturnValue;taint",
55+
"com.google.common.io;CharStreams;false;copy;(Readable,Appendable);;Argument[0];Argument[1];taint",
56+
"com.google.common.io;CharStreams;false;readLines;(Readable);;Argument[0];ReturnValue;taint",
57+
"com.google.common.io;CharStreams;false;toString;(Readable);;Argument[0];ReturnValue;taint",
58+
"com.google.common.io;Closer;true;register;;;Argument[0];ReturnValue;value",
59+
"com.google.common.io;Files;false;getFileExtension;(String);;Argument[0];ReturnValue;taint",
60+
"com.google.common.io;Files;false;getNameWithoutExtension;(String);;Argument[0];ReturnValue;taint",
61+
"com.google.common.io;Files;false;simplifyPath;(String);;Argument[0];ReturnValue;taint",
62+
"com.google.common.io;MoreFiles;false;getFileExtension;(Path);;Argument[0];ReturnValue;taint",
63+
"com.google.common.io;MoreFiles;false;getNameWithoutExtension;(Path);;Argument[0];ReturnValue;taint",
64+
"com.google.common.io;LineReader;false;LineReader;(Readable);;Argument[0];ReturnValue;taint",
65+
"com.google.common.io;LineReader;true;readLine;();;Argument[-1];ReturnValue;taint",
66+
"com.google.common.io;ByteArrayDataOutput;true;toByteArray;();;Argument[-1];ReturnValue;taint",
67+
"com.google.common.io;ByteArrayDataOutput;true;write;(byte[]);;Argument[0];Argument[-1];taint",
68+
"com.google.common.io;ByteArrayDataOutput;true;write;(byte[],int,int);;Argument[0];Argument[-1];taint",
69+
"com.google.common.io;ByteArrayDataOutput;true;write;(int);;Argument[0];Argument[-1];taint",
70+
"com.google.common.io;ByteArrayDataOutput;true;writeByte;(int);;Argument[0];Argument[-1];taint",
71+
"com.google.common.io;ByteArrayDataOutput;true;writeBytes;(String);;Argument[0];Argument[-1];taint",
72+
"com.google.common.io;ByteArrayDataOutput;true;writeChar;(int);;Argument[0];Argument[-1];taint",
73+
"com.google.common.io;ByteArrayDataOutput;true;writeChars;(String);;Argument[0];Argument[-1];taint",
74+
"com.google.common.io;ByteArrayDataOutput;true;writeDouble;(double);;Argument[0];Argument[-1];taint",
75+
"com.google.common.io;ByteArrayDataOutput;true;writeFloat;(float);;Argument[0];Argument[-1];taint",
76+
"com.google.common.io;ByteArrayDataOutput;true;writeInt;(int);;Argument[0];Argument[-1];taint",
77+
"com.google.common.io;ByteArrayDataOutput;true;writeLong;(long);;Argument[0];Argument[-1];taint",
78+
"com.google.common.io;ByteArrayDataOutput;true;writeShort;(int);;Argument[0];Argument[-1];taint",
79+
"com.google.common.io;ByteArrayDataOutput;true;writeUTF;(String);;Argument[0];Argument[-1];taint"
80+
]
81+
}
82+
}
83+
84+
private class GuavaIoSinkCsv extends SinkModelCsv {
85+
override predicate row(string row) {
86+
row =
87+
[
88+
//"package;type;overrides;name;signature;ext;inputspec;kind",
89+
"com.google.common.io;Resources;false;asByteSource;(URL);;Argument[0];url-open-stream",
90+
"com.google.common.io;Resources;false;asCharSource;(URL,Charset);;Argument[0];url-open-stream",
91+
"com.google.common.io;Resources;false;copy;(URL,OutputStream);;Argument[0];url-open-stream",
92+
"com.google.common.io;Resources;false;asByteSource;(URL);;Argument[0];url-open-stream",
93+
"com.google.common.io;Resources;false;readLines;;;Argument[0];url-open-stream",
94+
"com.google.common.io;Resources;false;toByteArray;(URL);;Argument[0];url-open-stream",
95+
"com.google.common.io;Resources;false;toString;(URL,Charset);;Argument[0];url-open-stream"
96+
]
97+
}
98+
}

java/ql/test/library-tests/frameworks/guava/TestCollect.java

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,20 @@ void test1() {
1414
String x = taint();
1515

1616
ImmutableSet<String> xs = ImmutableSet.of(x, "y", "z");
17-
sink(xs.asList());
17+
sink(xs.asList()); // $numTaintFlow=1
1818

1919
ImmutableSet<String> ys = ImmutableSet.of("a", "b", "c");
2020

21-
sink(Sets.filter(Sets.union(xs, ys), y -> true));
21+
sink(Sets.filter(Sets.union(xs, ys), y -> true)); // $numTaintFlow=1
2222

23-
sink(Sets.newHashSet("a", "b", "c", "d", x));
23+
sink(Sets.newHashSet("a", "b", "c", "d", x)); // $numTaintFlow=1
2424
}
2525

2626
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
27+
sink(ImmutableList.of(taint(), taint(), taint(), taint())); // $numTaintFlow=4
28+
sink(ImmutableMap.of(taint(), taint(), taint(), taint())); // $numTaintFlow=2
29+
sink(ImmutableMultimap.of(taint(), taint(), taint(), taint())); // $numTaintFlow=2
30+
sink(ImmutableTable.of(taint(),taint(), taint())); // $numTaintFlow=1
3131
}
3232

3333
void test3() {
@@ -38,20 +38,20 @@ void test3() {
3838
b.add("a");
3939
sink(b);
4040
b.add(x);
41-
sink(b.build());
41+
sink(b.build()); // $numTaintFlow=1
4242

4343
b = ImmutableList.builder();
4444

4545
b.add("a").add(x);
46-
sink(b.build());
46+
sink(b.build()); // $numTaintFlow=1
4747

48-
sink(ImmutableList.builder().add("a").add(x).build());
48+
sink(ImmutableList.builder().add("a").add(x).build()); // $numTaintFlow=1
4949

5050
ImmutableMap.Builder<String, String> b2 = ImmutableMap.builder();
5151
b2.put(x,"v");
5252
sink(b2);
5353
b2.put("k",x);
54-
sink(b2.build());
54+
sink(b2.build()); // $numTaintFlow=1
5555
}
5656

5757
void test4(Table<String, String, String> t1, Table<String, String, String> t2, Table<String, String, String> t3) {
@@ -61,62 +61,62 @@ void test4(Table<String, String, String> t1, Table<String, String, String> t2, T
6161
t1.put("r", x, "v");
6262
sink(t1);
6363
t1.put("r", "c", x);
64-
sink(t1);
65-
sink(t1.row("r"));
64+
sink(t1); // $numTaintFlow=1
65+
sink(t1.row("r")); // $numTaintFlow=1
6666

6767
t2.putAll(t1);
6868
for (Table.Cell<String,String,String> c : t2.cellSet()) {
69-
sink(c.getValue());
69+
sink(c.getValue()); // $numTaintFlow=1
7070
}
7171

72-
sink(t1.remove("r", "c"));
72+
sink(t1.remove("r", "c")); // $numTaintFlow=1
7373

7474
t3.row("r").put("c", x);
75-
sink(t3); // Not detected
75+
sink(t3); // $ MISSING:numTaintFlow=1
7676
}
7777

7878
void test4(Multimap<String, String> m1, Multimap<String, String> m2, Multimap<String, String> m3,
7979
Multimap<String, String> m4, Multimap<String, String> m5){
8080
String x = taint();
8181
m1.put("k", x);
82-
sink(m1);
83-
sink(m1.get("k"));
82+
sink(m1); // $numTaintFlow=1
83+
sink(m1.get("k")); // $numTaintFlow=1
8484

8585
m2.putAll("k", ImmutableList.of("a", x, "b"));
86-
sink(m2);
86+
sink(m2); // $numTaintFlow=1
8787

8888
m3.putAll(m1);
89-
sink(m3);
89+
sink(m3); // $numTaintFlow=1
9090

9191
m4.replaceValues("k", m1.replaceValues("k", ImmutableList.of("a")));
9292
for (Map.Entry<String, String> e : m4.entries()) {
93-
sink(e.getValue());
93+
sink(e.getValue()); // $numTaintFlow=1
9494
}
9595

9696
m5.asMap().get("k").add(x);
97-
sink(m5); // Not detected
97+
sink(m5); // $ MISSING:numTaintFlow=1
9898
}
9999

100100
void test5(Comparator<String> comp, SortedSet<String> sorS, SortedMap<String, String> sorM) {
101101
ImmutableSortedSet<String> s = ImmutableSortedSet.of(taint());
102102

103-
sink(s);
104-
sink(ImmutableSortedSet.copyOf(s));
105-
sink(ImmutableSortedSet.copyOf(comp, s));
103+
sink(s); // $numTaintFlow=1
104+
sink(ImmutableSortedSet.copyOf(s)); // $numTaintFlow=1
105+
sink(ImmutableSortedSet.copyOf(comp, s)); // $numTaintFlow=1
106106

107107
sorS.add(taint());
108-
sink(ImmutableSortedSet.copyOfSorted(sorS));
108+
sink(ImmutableSortedSet.copyOfSorted(sorS)); // $numTaintFlow=1
109109

110-
sink(ImmutableList.sortedCopyOf(s));
111-
sink(ImmutableList.sortedCopyOf(comp, s));
110+
sink(ImmutableList.sortedCopyOf(s)); // $numTaintFlow=1
111+
sink(ImmutableList.sortedCopyOf(comp, s)); // $numTaintFlow=1
112112

113113
ImmutableSortedMap<String, String> m = ImmutableSortedMap.of("k", taint());
114114

115-
sink(m);
116-
sink(ImmutableSortedMap.copyOf(m));
117-
sink(ImmutableSortedMap.copyOf(m, comp));
115+
sink(m); // $numTaintFlow=1
116+
sink(ImmutableSortedMap.copyOf(m)); // $numTaintFlow=1
117+
sink(ImmutableSortedMap.copyOf(m, comp)); // $numTaintFlow=1
118118

119119
sorM.put("k", taint());
120-
sink(ImmutableSortedMap.copyOfSorted(sorM));
120+
sink(ImmutableSortedMap.copyOfSorted(sorM)); // $numTaintFlow=1
121121
}
122122
}

0 commit comments

Comments
 (0)