From d67de88d34658926588fc8cfa28f3ecf477225d2 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Tue, 23 Feb 2021 14:25:48 +0000 Subject: [PATCH 01/12] Model Guava IO package --- .../semmle/code/java/frameworks/guava/IO.qll | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 java/ql/src/semmle/code/java/frameworks/guava/IO.qll diff --git a/java/ql/src/semmle/code/java/frameworks/guava/IO.qll b/java/ql/src/semmle/code/java/frameworks/guava/IO.qll new file mode 100644 index 000000000000..ae9a90479b2d --- /dev/null +++ b/java/ql/src/semmle/code/java/frameworks/guava/IO.qll @@ -0,0 +1,55 @@ +/** Definitions of taint steps in the IO packae of the Guava framework */ + +import java +private import semmle.code.java.dataflow.DataFlow +private import semmle.code.java.dataflow.ExternalFlow + +private class GuavaIoCsv extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + //"package;type;overrides;name;signature;ext;inputspec;outputspec;kind", + "com.google.common.io;BaseEncoding;true;decode;(CharSequence);;Argument[0];ReturnValue;taint", + "com.google.common.io;BaseEncoding;true;decodingStream;(Reader);;Argument[0];ReturnValue;taint", + "com.google.common.io;BaseEncoding;true;decodingSource;(CharSource);;Argument[0];ReturnValue;taint", + "com.google.common.io;BaseEncoding;true;encode;(byte[]);;Argument[0];ReturnValue;taint", + "com.google.common.io;BaseEncoding;true;encode;(byte[],int,int);;Argument[0];ReturnValue;taint", + "com.google.common.io;ByteSource;true;asCharSource;(Charset);;Argument[0];ReturnValue;taint", + "com.google.common.io;ByteSource;true;concat;;;Argument[0];ReturnValue;taint", + "com.google.common.io;ByteSource;true;openStream;();;Argument[-1];ReturnValue;taint", + "com.google.common.io;ByteSource;true;openBufferedStream;();;Argument[-1];ReturnValue;taint", + "com.google.common.io;ByteSource;true;read;();;Argument[-1];ReturnValue;taint", + "com.google.common.io;ByteSource;true;slice;(long,long);;Argument[-1];ReturnValue;taint", + "com.google.common.io;ByteSource;true;wrap;(byte[]);;Argument[0];ReturnValue;taint", + "com.google.common.io;ByteStreams;false;copy;(InputStream,OutputStream);;Argument[0];Argument[1];taint", + "com.google.common.io;ByteStreams;false;limit;(InputStream,long);;Argument[0];ReturnValue;taint", + "com.google.common.io;ByteStreams;false;newDataInput;(byte[]);;Argument[0];ReturnValue;taint", + "com.google.common.io;ByteStreams;false;newDataInput;(byte[],int);;Argument[0];ReturnValue;taint", + "com.google.common.io;ByteStreams;false;newDataInput;(ByteArrayInputStream);;Argument[0];ReturnValue;taint", + "com.google.common.io;ByteStreams;false;read;(InputStream,byte[],int,int);;Argument[0];Argument[-1];taint", + "com.google.common.io;ByteStreams;false;readFully;(InputStream,byte[]);;Argument[0];Argument[1];taint", + "com.google.common.io;ByteStreams;false;readFully;(InputStream,byte[],int,int);;Argument[0];Argument[1];taint", + "com.google.common.io;ByteStreams;false;toByteArray;(InputStream);;Argument[0];ReturnValue;taint", + "com.google.common.io;CharSource;true;asByteSource;(Charset);;Argument[0];ReturnValue;taint", + "com.google.common.io;CharSource;true;concat;;;Argument[0];ReturnValue;taint", + "com.google.common.io;CharSource;true;copyTo;(Appendable);;Argument[-1];Argument[0];taint", + "com.google.common.io;CharSource;true;openStream;();;Argument[-1];ReturnValue;taint", + "com.google.common.io;CharSource;true;openBufferedStream;();;Argument[-1];ReturnValue;taint", + "com.google.common.io;CharSource;true;read;();;Argument[-1];ReturnValue;taint", + "com.google.common.io;CharSource;true;readFirstLine;();;Argument[-1];ReturnValue;taint", + "com.google.common.io;CharSource;true;readLines;();;Argument[-1];ReturnValue;taint", + "com.google.common.io;CharSource;true;wrap;(CharSequence);;Argument[0];ReturnValue;taint", + "com.google.common.io;CharStreams;false;copy;(Readable,Appendable);;Argument[0];Argument[1];taint", + "com.google.common.io;CharStreams;false;readLines;(Readable);;Argument[0];Argument[-1];taint", + "com.google.common.io;CharStreams;false;toString;(Readable);;Argument[0];ReturnValue;taint", + "com.google.common.io;Closer;true;register;;;Argument[0];ReturnValue;value", + "com.google.common.io;Files;false;getFileExtension;(String);;Argument[0];ReturnValue;taint", + "com.google.common.io;Files;false;getNameWithoutExtension;(String);;Argument[0];ReturnValue;taint", + "com.google.common.io;Files;false;simplifyPath;(String);;Argument[0];ReturnValue;taint", + "com.google.common.io;MoreFiles;false;getFileExtension;(Path);;Argument[0];ReturnValue;taint", + "com.google.common.io;MoreFiles;false;getNameWithoutExtension;(Path);;Argument[0];ReturnValue;taint", + "com.google.common.io;LineReader;false;LineReader;(Reader);;Argument[0];ReturnValue;taint", + "com.google.common.io;LineReader;false;readLine;();;Argument[-1];ReturnValue;taint" + ] + } +} From 56e611faaac23757168418e8fae26f8e1939be4d Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Mon, 1 Mar 2021 15:05:19 +0000 Subject: [PATCH 02/12] Switch existing test cases to inline expectations --- .../frameworks/guava/TestCollect.java | 64 +++++++++---------- .../frameworks/guava/TestStrings.java | 38 +++++------ .../frameworks/guava/flow.expected | 52 --------------- .../library-tests/frameworks/guava/flow.ql | 19 +++++- 4 files changed, 67 insertions(+), 106 deletions(-) diff --git a/java/ql/test/library-tests/frameworks/guava/TestCollect.java b/java/ql/test/library-tests/frameworks/guava/TestCollect.java index c5f01f2d2d1a..382b2de64cbd 100644 --- a/java/ql/test/library-tests/frameworks/guava/TestCollect.java +++ b/java/ql/test/library-tests/frameworks/guava/TestCollect.java @@ -14,20 +14,20 @@ void test1() { String x = taint(); ImmutableSet xs = ImmutableSet.of(x, "y", "z"); - sink(xs.asList()); + sink(xs.asList()); // $numTaintFlow=1 ImmutableSet ys = ImmutableSet.of("a", "b", "c"); - sink(Sets.filter(Sets.union(xs, ys), y -> true)); + sink(Sets.filter(Sets.union(xs, ys), y -> true)); // $numTaintFlow=1 - sink(Sets.newHashSet("a", "b", "c", "d", x)); + sink(Sets.newHashSet("a", "b", "c", "d", x)); // $numTaintFlow=1 } void test2() { - sink(ImmutableList.of(taint(), taint(), taint(), taint())); // expect 4 alerts - sink(ImmutableMap.of(taint(), taint(), taint(), taint())); // expect 2 alerts - sink(ImmutableMultimap.of(taint(), taint(), taint(), taint())); // expect 2 alerts - sink(ImmutableTable.of(taint(),taint(), taint())); // expect 1 alert + sink(ImmutableList.of(taint(), taint(), taint(), taint())); // $numTaintFlow=4 + sink(ImmutableMap.of(taint(), taint(), taint(), taint())); // $numTaintFlow=2 + sink(ImmutableMultimap.of(taint(), taint(), taint(), taint())); // $numTaintFlow=2 + sink(ImmutableTable.of(taint(),taint(), taint())); // $numTaintFlow=1 } void test3() { @@ -38,20 +38,20 @@ void test3() { b.add("a"); sink(b); b.add(x); - sink(b.build()); + sink(b.build()); // $numTaintFlow=1 b = ImmutableList.builder(); b.add("a").add(x); - sink(b.build()); + sink(b.build()); // $numTaintFlow=1 - sink(ImmutableList.builder().add("a").add(x).build()); + sink(ImmutableList.builder().add("a").add(x).build()); // $numTaintFlow=1 ImmutableMap.Builder b2 = ImmutableMap.builder(); b2.put(x,"v"); sink(b2); b2.put("k",x); - sink(b2.build()); + sink(b2.build()); // $numTaintFlow=1 } void test4(Table t1, Table t2, Table t3) { @@ -61,62 +61,62 @@ void test4(Table t1, Table t2, T t1.put("r", x, "v"); sink(t1); t1.put("r", "c", x); - sink(t1); - sink(t1.row("r")); + sink(t1); // $numTaintFlow=1 + sink(t1.row("r")); // $numTaintFlow=1 t2.putAll(t1); for (Table.Cell c : t2.cellSet()) { - sink(c.getValue()); + sink(c.getValue()); // $numTaintFlow=1 } - sink(t1.remove("r", "c")); + sink(t1.remove("r", "c")); // $numTaintFlow=1 t3.row("r").put("c", x); - sink(t3); // Not detected + sink(t3); // MISSING:$numTaintFlow=1 } void test4(Multimap m1, Multimap m2, Multimap m3, Multimap m4, Multimap m5){ String x = taint(); m1.put("k", x); - sink(m1); - sink(m1.get("k")); + sink(m1); // $numTaintFlow=1 + sink(m1.get("k")); // $numTaintFlow=1 m2.putAll("k", ImmutableList.of("a", x, "b")); - sink(m2); + sink(m2); // $numTaintFlow=1 m3.putAll(m1); - sink(m3); + sink(m3); // $numTaintFlow=1 m4.replaceValues("k", m1.replaceValues("k", ImmutableList.of("a"))); for (Map.Entry e : m4.entries()) { - sink(e.getValue()); + sink(e.getValue()); // $numTaintFlow=1 } m5.asMap().get("k").add(x); - sink(m5); // Not detected + sink(m5); // MISSING:$numTaintFlow=1 } void test5(Comparator comp, SortedSet sorS, SortedMap sorM) { ImmutableSortedSet s = ImmutableSortedSet.of(taint()); - sink(s); - sink(ImmutableSortedSet.copyOf(s)); - sink(ImmutableSortedSet.copyOf(comp, s)); + sink(s); // $numTaintFlow=1 + sink(ImmutableSortedSet.copyOf(s)); // $numTaintFlow=1 + sink(ImmutableSortedSet.copyOf(comp, s)); // $numTaintFlow=1 sorS.add(taint()); - sink(ImmutableSortedSet.copyOfSorted(sorS)); + sink(ImmutableSortedSet.copyOfSorted(sorS)); // $numTaintFlow=1 - sink(ImmutableList.sortedCopyOf(s)); - sink(ImmutableList.sortedCopyOf(comp, s)); + sink(ImmutableList.sortedCopyOf(s)); // $numTaintFlow=1 + sink(ImmutableList.sortedCopyOf(comp, s)); // $numTaintFlow=1 ImmutableSortedMap m = ImmutableSortedMap.of("k", taint()); - sink(m); - sink(ImmutableSortedMap.copyOf(m)); - sink(ImmutableSortedMap.copyOf(m, comp)); + sink(m); // $numTaintFlow=1 + sink(ImmutableSortedMap.copyOf(m)); // $numTaintFlow=1 + sink(ImmutableSortedMap.copyOf(m, comp)); // $numTaintFlow=1 sorM.put("k", taint()); - sink(ImmutableSortedMap.copyOfSorted(sorM)); + sink(ImmutableSortedMap.copyOfSorted(sorM)); // $numTaintFlow=1 } } \ No newline at end of file diff --git a/java/ql/test/library-tests/frameworks/guava/TestStrings.java b/java/ql/test/library-tests/frameworks/guava/TestStrings.java index e85cb0bc9655..4c2e38654618 100644 --- a/java/ql/test/library-tests/frameworks/guava/TestStrings.java +++ b/java/ql/test/library-tests/frameworks/guava/TestStrings.java @@ -14,14 +14,14 @@ void sink(Object o) {} void test1() { String x = taint(); - sink(Strings.padStart(x, 10, ' ')); - sink(Strings.padEnd(x, 10, ' ')); - sink(Strings.repeat(x, 3)); - sink(Strings.emptyToNull(Strings.nullToEmpty(x))); - sink(Strings.lenientFormat(x, 3)); - sink(Strings.commonPrefix(x, "abc")); - sink(Strings.commonSuffix(x, "cde")); - sink(Strings.lenientFormat("%s = %s", x, 3)); + sink(Strings.padStart(x, 10, ' ')); // $numTaintFlow=1 + sink(Strings.padEnd(x, 10, ' ')); // $numTaintFlow=1 + sink(Strings.repeat(x, 3)); // $numTaintFlow=1 + sink(Strings.emptyToNull(Strings.nullToEmpty(x))); // $numTaintFlow=1 + sink(Strings.lenientFormat(x, 3)); // $numTaintFlow=1 + sink(Strings.commonPrefix(x, "abc")); + sink(Strings.commonSuffix(x, "cde")); + sink(Strings.lenientFormat("%s = %s", x, 3)); // $numTaintFlow=1 } void test2() { @@ -29,10 +29,10 @@ void test2() { Splitter s = Splitter.on(x).omitEmptyStrings(); sink(s.split("x y z")); - sink(s.split(x)); - sink(s.splitToList(x)); + sink(s.split(x)); // $numTaintFlow=1 + sink(s.splitToList(x)); // $numTaintFlow=1 sink(s.withKeyValueSeparator("=").split("a=b")); - sink(s.withKeyValueSeparator("=").split(x)); + sink(s.withKeyValueSeparator("=").split(x)); // $numTaintFlow=1 } void test3() { @@ -43,20 +43,20 @@ void test3() { StringBuilder sb = new StringBuilder(); sink(safeJoiner.appendTo(sb, "a", "b", "c")); sink(sb.toString()); - sink(taintedJoiner.appendTo(sb, "a", "b", "c")); - sink(sb.toString()); - sink(safeJoiner.appendTo(sb, "a", "b", "c")); - sink(sb.toString()); + sink(taintedJoiner.appendTo(sb, "a", "b", "c")); // $numTaintFlow=1 + sink(sb.toString()); // $numTaintFlow=1 + sink(safeJoiner.appendTo(sb, "a", "b", "c")); // $numTaintFlow=1 + sink(sb.toString()); // $numTaintFlow=1 sb = new StringBuilder(); - sink(safeJoiner.appendTo(sb, x, x)); + sink(safeJoiner.appendTo(sb, x, x)); // $numTaintFlow=1 Map m = new HashMap(); m.put("k", "v"); sink(safeJoiner.withKeyValueSeparator("=").join(m)); - sink(safeJoiner.withKeyValueSeparator(x).join(m)); - sink(taintedJoiner.useForNull("(null)").withKeyValueSeparator("=").join(m)); + sink(safeJoiner.withKeyValueSeparator(x).join(m)); // $numTaintFlow=1 + sink(taintedJoiner.useForNull("(null)").withKeyValueSeparator("=").join(m)); // $numTaintFlow=1 m.put("k2", x); - sink(safeJoiner.withKeyValueSeparator("=").join(m)); + sink(safeJoiner.withKeyValueSeparator("=").join(m)); // $numTaintFlow=1 } } \ No newline at end of file diff --git a/java/ql/test/library-tests/frameworks/guava/flow.expected b/java/ql/test/library-tests/frameworks/guava/flow.expected index 52276485cf92..e69de29bb2d1 100644 --- a/java/ql/test/library-tests/frameworks/guava/flow.expected +++ b/java/ql/test/library-tests/frameworks/guava/flow.expected @@ -1,52 +0,0 @@ -| TestCollect.java:14:20:14:26 | taint(...) | TestCollect.java:17:14:17:24 | asList(...) | -| TestCollect.java:14:20:14:26 | taint(...) | TestCollect.java:21:14:21:55 | filter(...) | -| TestCollect.java:14:20:14:26 | taint(...) | TestCollect.java:23:14:23:51 | newHashSet(...) | -| TestCollect.java:27:31:27:37 | taint(...) | TestCollect.java:27:14:27:65 | of(...) | -| TestCollect.java:27:40:27:46 | taint(...) | TestCollect.java:27:14:27:65 | of(...) | -| TestCollect.java:27:49:27:55 | taint(...) | TestCollect.java:27:14:27:65 | of(...) | -| TestCollect.java:27:58:27:64 | taint(...) | TestCollect.java:27:14:27:65 | of(...) | -| TestCollect.java:28:39:28:45 | taint(...) | TestCollect.java:28:14:28:64 | of(...) | -| TestCollect.java:28:57:28:63 | taint(...) | TestCollect.java:28:14:28:64 | of(...) | -| TestCollect.java:29:44:29:50 | taint(...) | TestCollect.java:29:14:29:69 | of(...) | -| TestCollect.java:29:62:29:68 | taint(...) | TestCollect.java:29:14:29:69 | of(...) | -| TestCollect.java:30:49:30:55 | taint(...) | TestCollect.java:30:14:30:56 | of(...) | -| TestCollect.java:34:20:34:26 | taint(...) | TestCollect.java:41:14:41:22 | build(...) | -| TestCollect.java:34:20:34:26 | taint(...) | TestCollect.java:46:14:46:22 | build(...) | -| TestCollect.java:34:20:34:26 | taint(...) | TestCollect.java:48:14:48:60 | build(...) | -| TestCollect.java:34:20:34:26 | taint(...) | TestCollect.java:54:14:54:23 | build(...) | -| TestCollect.java:58:20:58:26 | taint(...) | TestCollect.java:64:14:64:15 | t1 | -| TestCollect.java:58:20:58:26 | taint(...) | TestCollect.java:65:14:65:24 | row(...) | -| TestCollect.java:58:20:58:26 | taint(...) | TestCollect.java:69:18:69:29 | getValue(...) | -| TestCollect.java:58:20:58:26 | taint(...) | TestCollect.java:72:14:72:32 | remove(...) | -| TestCollect.java:80:20:80:26 | taint(...) | TestCollect.java:82:14:82:15 | m1 | -| TestCollect.java:80:20:80:26 | taint(...) | TestCollect.java:83:14:83:24 | get(...) | -| TestCollect.java:80:20:80:26 | taint(...) | TestCollect.java:86:14:86:15 | m2 | -| TestCollect.java:80:20:80:26 | taint(...) | TestCollect.java:89:14:89:15 | m3 | -| TestCollect.java:80:20:80:26 | taint(...) | TestCollect.java:93:18:93:29 | getValue(...) | -| TestCollect.java:101:62:101:68 | taint(...) | TestCollect.java:103:14:103:14 | s | -| TestCollect.java:101:62:101:68 | taint(...) | TestCollect.java:104:14:104:41 | copyOf(...) | -| TestCollect.java:101:62:101:68 | taint(...) | TestCollect.java:105:14:105:47 | copyOf(...) | -| TestCollect.java:101:62:101:68 | taint(...) | TestCollect.java:110:14:110:42 | sortedCopyOf(...) | -| TestCollect.java:101:62:101:68 | taint(...) | TestCollect.java:111:14:111:48 | sortedCopyOf(...) | -| TestCollect.java:107:18:107:24 | taint(...) | TestCollect.java:108:14:108:50 | copyOfSorted(...) | -| TestCollect.java:113:75:113:81 | taint(...) | TestCollect.java:115:14:115:14 | m | -| TestCollect.java:113:75:113:81 | taint(...) | TestCollect.java:116:14:116:41 | copyOf(...) | -| TestCollect.java:113:75:113:81 | taint(...) | TestCollect.java:117:14:117:47 | copyOf(...) | -| TestCollect.java:119:23:119:29 | taint(...) | TestCollect.java:120:14:120:50 | copyOfSorted(...) | -| TestStrings.java:15:20:15:26 | taint(...) | TestStrings.java:17:14:17:41 | padStart(...) | -| TestStrings.java:15:20:15:26 | taint(...) | TestStrings.java:18:14:18:39 | padEnd(...) | -| TestStrings.java:15:20:15:26 | taint(...) | TestStrings.java:19:14:19:33 | repeat(...) | -| TestStrings.java:15:20:15:26 | taint(...) | TestStrings.java:20:14:20:56 | emptyToNull(...) | -| TestStrings.java:15:20:15:26 | taint(...) | TestStrings.java:21:14:21:40 | lenientFormat(...) | -| TestStrings.java:15:20:15:26 | taint(...) | TestStrings.java:24:14:24:51 | lenientFormat(...) | -| TestStrings.java:28:20:28:26 | taint(...) | TestStrings.java:32:14:32:23 | split(...) | -| TestStrings.java:28:20:28:26 | taint(...) | TestStrings.java:33:14:33:29 | splitToList(...) | -| TestStrings.java:28:20:28:26 | taint(...) | TestStrings.java:35:14:35:50 | split(...) | -| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:46:14:46:54 | appendTo(...) | -| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:47:14:47:26 | toString(...) | -| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:48:14:48:51 | appendTo(...) | -| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:49:14:49:26 | toString(...) | -| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:52:14:52:42 | appendTo(...) | -| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:57:14:57:56 | join(...) | -| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:58:14:58:82 | join(...) | -| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:60:14:60:58 | join(...) | diff --git a/java/ql/test/library-tests/frameworks/guava/flow.ql b/java/ql/test/library-tests/frameworks/guava/flow.ql index fa79cd151c4c..cdab4fcb3e6c 100644 --- a/java/ql/test/library-tests/frameworks/guava/flow.ql +++ b/java/ql/test/library-tests/frameworks/guava/flow.ql @@ -1,5 +1,6 @@ import java import semmle.code.java.dataflow.TaintTracking +import TestUtilities.InlineExpectationsTest class Conf extends TaintTracking::Configuration { Conf() { this = "qltest:frameworks:guava" } @@ -13,6 +14,18 @@ class Conf extends TaintTracking::Configuration { } } -from DataFlow::Node src, DataFlow::Node sink, Conf conf -where conf.hasFlow(src, sink) -select src, sink +class HasFlowTest extends InlineExpectationsTest { + HasFlowTest() { this = "HasFlowTest" } + + override string getARelevantTag() { result = "numTaintFlow" } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "numTaintFlow" and + exists(DataFlow::Node src, DataFlow::Node sink, Conf conf, int num | conf.hasFlow(src, sink) | + value = num.toString() and + sink.getLocation() = location and + element = sink.toString() and + num = strictcount(DataFlow::Node src2 | conf.hasFlow(src2, sink)) + ) + } +} From c12f8035c4341c1192f1e798cf9b38e443e3d849 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Tue, 2 Mar 2021 12:41:53 +0000 Subject: [PATCH 03/12] Add stubs for unit tests --- .../com/google/common/base/Function.java | 25 ++++ .../com/google/common/base/Optional.java | 77 ++++++++++ .../com/google/common/base/Predicate.java | 29 ++++ .../com/google/common/base/Supplier.java | 21 +++ .../common/graph/SuccessorsFunction.java | 22 +++ .../com/google/common/graph/Traverser.java | 52 +++++++ .../com/google/common/hash/Funnel.java | 21 +++ .../com/google/common/hash/HashCode.java | 64 +++++++++ .../com/google/common/hash/HashFunction.java | 42 ++++++ .../com/google/common/hash/Hasher.java | 66 +++++++++ .../com/google/common/hash/PrimitiveSink.java | 46 ++++++ .../com/google/common/io/BaseEncoding.java | 81 +++++++++++ .../google/common/io/ByteArrayDataInput.java | 64 +++++++++ .../google/common/io/ByteArrayDataOutput.java | 63 +++++++++ .../com/google/common/io/ByteProcessor.java | 23 +++ .../com/google/common/io/ByteSink.java | 39 ++++++ .../com/google/common/io/ByteSource.java | 96 +++++++++++++ .../com/google/common/io/ByteStreams.java | 90 ++++++++++++ .../com/google/common/io/CharSink.java | 48 +++++++ .../com/google/common/io/CharSource.java | 101 ++++++++++++++ .../com/google/common/io/CharStreams.java | 53 +++++++ .../com/google/common/io/Closer.java | 47 +++++++ .../com/google/common/io/FileWriteMode.java | 18 +++ .../com/google/common/io/Files.java | 131 ++++++++++++++++++ .../com/google/common/io/LineProcessor.java | 23 +++ .../com/google/common/io/LineReader.java | 26 ++++ .../com/google/common/io/MoreFiles.java | 88 ++++++++++++ .../common/io/RecursiveDeleteOption.java | 20 +++ .../checker/nullness/qual/Nullable.java | 2 + 29 files changed, 1478 insertions(+) create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/base/Function.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/base/Optional.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/base/Predicate.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/base/Supplier.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/graph/SuccessorsFunction.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/graph/Traverser.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/hash/Funnel.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/hash/HashCode.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/hash/HashFunction.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/hash/Hasher.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/hash/PrimitiveSink.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/io/BaseEncoding.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/io/ByteArrayDataInput.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/io/ByteArrayDataOutput.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/io/ByteProcessor.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/io/ByteSink.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/io/ByteSource.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/io/ByteStreams.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/io/CharSink.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/io/CharSource.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/io/CharStreams.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/io/Closer.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/io/FileWriteMode.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/io/Files.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/io/LineProcessor.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/io/LineReader.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/io/MoreFiles.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/io/RecursiveDeleteOption.java create mode 100644 java/ql/test/stubs/guava-30.0/org/checkerframework/checker/nullness/qual/Nullable.java diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/base/Function.java b/java/ql/test/stubs/guava-30.0/com/google/common/base/Function.java new file mode 100644 index 000000000000..75acf7f8a542 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/base/Function.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2007 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.common.base; +import org.checkerframework.checker.nullness.qual.Nullable; + +public interface Function extends java.util.function.Function { + @Override + T apply(@Nullable F input); + + @Override + boolean equals(@Nullable Object object); + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/base/Optional.java b/java/ql/test/stubs/guava-30.0/com/google/common/base/Optional.java new file mode 100644 index 000000000000..f6f757ac9944 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/base/Optional.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2011 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.common.base; +import java.io.Serializable; +import java.util.Set; +import org.checkerframework.checker.nullness.qual.Nullable; + +public abstract class Optional implements Serializable { + public static Optional absent() { + return null; + } + + public static Optional of(T reference) { + return null; + } + + public static Optional fromNullable(@Nullable T nullableReference) { + return null; + } + + public static @Nullable Optional fromJavaUtil( + java.util.Optional javaUtilOptional) { + return null; + } + + public static java.util.Optional toJavaUtil( + @Nullable Optional googleOptional) { + return null; + } + + public java.util.Optional toJavaUtil() { + return null; + } + + public abstract boolean isPresent(); + + public abstract T get(); + + public abstract T or(T defaultValue); + + public abstract Optional or(Optional secondChoice); + + public abstract T or(Supplier supplier); + + public abstract @Nullable T orNull(); + + public abstract Set asSet(); + + public abstract Optional transform(Function function); + + @Override + public abstract boolean equals(@Nullable Object object); + + @Override + public abstract int hashCode(); + + @Override + public abstract String toString(); + + public static Iterable presentInstances( + final Iterable> optionals) { + return null; + } + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/base/Predicate.java b/java/ql/test/stubs/guava-30.0/com/google/common/base/Predicate.java new file mode 100644 index 000000000000..1adc6a1caed4 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/base/Predicate.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2007 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.common.base; +import org.checkerframework.checker.nullness.qual.Nullable; + +public interface Predicate extends java.util.function.Predicate { + boolean apply(@Nullable T input); + + @Override + boolean equals(@Nullable Object object); + + @Override + default boolean test(@Nullable T input) { + return false; + } + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/base/Supplier.java b/java/ql/test/stubs/guava-30.0/com/google/common/base/Supplier.java new file mode 100644 index 000000000000..a9be9855c8cc --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/base/Supplier.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2007 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.common.base; + +public interface Supplier extends java.util.function.Supplier { + @Override + T get(); + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/graph/SuccessorsFunction.java b/java/ql/test/stubs/guava-30.0/com/google/common/graph/SuccessorsFunction.java new file mode 100644 index 000000000000..1a341489a7a4 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/graph/SuccessorsFunction.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2014 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.common.graph; + +public interface SuccessorsFunction { + Iterable successors(N node); + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/graph/Traverser.java b/java/ql/test/stubs/guava-30.0/com/google/common/graph/Traverser.java new file mode 100644 index 000000000000..0d705a609b7f --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/graph/Traverser.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2017 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.common.graph; + +public abstract class Traverser { + public static Traverser forGraph(final SuccessorsFunction graph) { + return null; + } + + public static Traverser forTree(final SuccessorsFunction tree) { + return null; + } + + public final Iterable breadthFirst(N startNode) { + return null; + } + + public final Iterable breadthFirst(Iterable startNodes) { + return null; + } + + public final Iterable depthFirstPreOrder(N startNode) { + return null; + } + + public final Iterable depthFirstPreOrder(Iterable startNodes) { + return null; + } + + public final Iterable depthFirstPostOrder(N startNode) { + return null; + } + + public final Iterable depthFirstPostOrder(Iterable startNodes) { + return null; + } + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/hash/Funnel.java b/java/ql/test/stubs/guava-30.0/com/google/common/hash/Funnel.java new file mode 100644 index 000000000000..12866dd75480 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/hash/Funnel.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2011 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.common.hash; +import java.io.Serializable; + +public interface Funnel extends Serializable { + void funnel(T from, PrimitiveSink into); + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/hash/HashCode.java b/java/ql/test/stubs/guava-30.0/com/google/common/hash/HashCode.java new file mode 100644 index 000000000000..b63730ae4f74 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/hash/HashCode.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2011 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.common.hash; +import org.checkerframework.checker.nullness.qual.Nullable; + +public abstract class HashCode { + public abstract int bits(); + + public abstract int asInt(); + + public abstract long asLong(); + + public abstract long padToLong(); + + public abstract byte[] asBytes(); + + public int writeBytesTo(byte[] dest, int offset, int maxLength) { + return 0; + } + + public static HashCode fromInt(int hash) { + return null; + } + + public static HashCode fromLong(long hash) { + return null; + } + + public static HashCode fromBytes(byte[] bytes) { + return null; + } + + public static HashCode fromString(String string) { + return null; + } + + @Override + public final boolean equals(@Nullable Object object) { + return false; + } + + @Override + public final int hashCode() { + return 0; + } + + @Override + public final String toString() { + return null; + } + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/hash/HashFunction.java b/java/ql/test/stubs/guava-30.0/com/google/common/hash/HashFunction.java new file mode 100644 index 000000000000..44a8958cdc38 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/hash/HashFunction.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2011 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.common.hash; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; + +public interface HashFunction { + Hasher newHasher(); + + Hasher newHasher(int expectedInputSize); + + HashCode hashInt(int input); + + HashCode hashLong(long input); + + HashCode hashBytes(byte[] input); + + HashCode hashBytes(byte[] input, int off, int len); + + HashCode hashBytes(ByteBuffer input); + + HashCode hashUnencodedChars(CharSequence input); + + HashCode hashString(CharSequence input, Charset charset); + + HashCode hashObject(T instance, Funnel funnel); + + int bits(); + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/hash/Hasher.java b/java/ql/test/stubs/guava-30.0/com/google/common/hash/Hasher.java new file mode 100644 index 000000000000..0945f0f483ec --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/hash/Hasher.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2011 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.common.hash; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; + +public interface Hasher extends PrimitiveSink { + @Override + Hasher putByte(byte b); + + @Override + Hasher putBytes(byte[] bytes); + + @Override + Hasher putBytes(byte[] bytes, int off, int len); + + @Override + Hasher putBytes(ByteBuffer bytes); + + @Override + Hasher putShort(short s); + + @Override + Hasher putInt(int i); + + @Override + Hasher putLong(long l); + + @Override + Hasher putFloat(float f); + + @Override + Hasher putDouble(double d); + + @Override + Hasher putBoolean(boolean b); + + @Override + Hasher putChar(char c); + + @Override + Hasher putUnencodedChars(CharSequence charSequence); + + @Override + Hasher putString(CharSequence charSequence, Charset charset); + + Hasher putObject(T instance, Funnel funnel); + + HashCode hash(); + + @Override + int hashCode(); + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/hash/PrimitiveSink.java b/java/ql/test/stubs/guava-30.0/com/google/common/hash/PrimitiveSink.java new file mode 100644 index 000000000000..bb845a1f878f --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/hash/PrimitiveSink.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2011 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.common.hash; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; + +public interface PrimitiveSink { + PrimitiveSink putByte(byte b); + + PrimitiveSink putBytes(byte[] bytes); + + PrimitiveSink putBytes(byte[] bytes, int off, int len); + + PrimitiveSink putBytes(ByteBuffer bytes); + + PrimitiveSink putShort(short s); + + PrimitiveSink putInt(int i); + + PrimitiveSink putLong(long l); + + PrimitiveSink putFloat(float f); + + PrimitiveSink putDouble(double d); + + PrimitiveSink putBoolean(boolean b); + + PrimitiveSink putChar(char c); + + PrimitiveSink putUnencodedChars(CharSequence charSequence); + + PrimitiveSink putString(CharSequence charSequence, Charset charset); + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/io/BaseEncoding.java b/java/ql/test/stubs/guava-30.0/com/google/common/io/BaseEncoding.java new file mode 100644 index 000000000000..0b0ea815447f --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/io/BaseEncoding.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2012 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.common.io; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; + +public abstract class BaseEncoding { + public static final class DecodingException extends IOException { + } + public String encode(byte[] bytes) { + return null; + } + + public final String encode(byte[] bytes, int off, int len) { + return null; + } + + public abstract OutputStream encodingStream(Writer writer); + + public final ByteSink encodingSink(final CharSink encodedSink) { + return null; + } + + public abstract boolean canDecode(CharSequence chars); + + public final byte[] decode(CharSequence chars) { + return null; + } + + public abstract InputStream decodingStream(Reader reader); + + public final ByteSource decodingSource(final CharSource encodedSource) { + return null; + } + + public abstract BaseEncoding omitPadding(); + + public abstract BaseEncoding withPadChar(char padChar); + + public abstract BaseEncoding withSeparator(String separator, int n); + + public abstract BaseEncoding upperCase(); + + public abstract BaseEncoding lowerCase(); + + public static BaseEncoding base64() { + return null; + } + + public static BaseEncoding base64Url() { + return null; + } + + public static BaseEncoding base32() { + return null; + } + + public static BaseEncoding base32Hex() { + return null; + } + + public static BaseEncoding base16() { + return null; + } + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/io/ByteArrayDataInput.java b/java/ql/test/stubs/guava-30.0/com/google/common/io/ByteArrayDataInput.java new file mode 100644 index 000000000000..022ff776d048 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/io/ByteArrayDataInput.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2009 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.common.io; +import java.io.DataInput; + +public interface ByteArrayDataInput extends DataInput { + @Override + void readFully(byte b[]); + + @Override + void readFully(byte b[], int off, int len); + + @Override + int skipBytes(int n); + + @Override + boolean readBoolean(); + + @Override + byte readByte(); + + @Override + int readUnsignedByte(); + + @Override + short readShort(); + + @Override + int readUnsignedShort(); + + @Override + char readChar(); + + @Override + int readInt(); + + @Override + long readLong(); + + @Override + float readFloat(); + + @Override + double readDouble(); + + @Override + String readLine(); + + @Override + String readUTF(); + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/io/ByteArrayDataOutput.java b/java/ql/test/stubs/guava-30.0/com/google/common/io/ByteArrayDataOutput.java new file mode 100644 index 000000000000..01908d9013d0 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/io/ByteArrayDataOutput.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2009 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.common.io; +import java.io.DataOutput; + +public interface ByteArrayDataOutput extends DataOutput { + @Override + void write(int b); + + @Override + void write(byte b[]); + + @Override + void write(byte b[], int off, int len); + + @Override + void writeBoolean(boolean v); + + @Override + void writeByte(int v); + + @Override + void writeShort(int v); + + @Override + void writeChar(int v); + + @Override + void writeInt(int v); + + @Override + void writeLong(long v); + + @Override + void writeFloat(float v); + + @Override + void writeDouble(double v); + + @Override + void writeChars(String s); + + @Override + void writeUTF(String s); + + @Override + void writeBytes(String s); + + byte[] toByteArray(); + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/io/ByteProcessor.java b/java/ql/test/stubs/guava-30.0/com/google/common/io/ByteProcessor.java new file mode 100644 index 000000000000..1e532fff65d6 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/io/ByteProcessor.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2009 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.common.io; +import java.io.IOException; + +public interface ByteProcessor { + boolean processBytes(byte[] buf, int off, int len) throws IOException; + + T getResult(); + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/io/ByteSink.java b/java/ql/test/stubs/guava-30.0/com/google/common/io/ByteSink.java new file mode 100644 index 000000000000..14ab8fe13855 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/io/ByteSink.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2012 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.common.io; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.Charset; + +public abstract class ByteSink { + public CharSink asCharSink(Charset charset) { + return null; + } + + public abstract OutputStream openStream() throws IOException; + + public OutputStream openBufferedStream() throws IOException { + return null; + } + + public void write(byte[] bytes) throws IOException { + } + + public long writeFrom(InputStream input) throws IOException { + return 0; + } + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/io/ByteSource.java b/java/ql/test/stubs/guava-30.0/com/google/common/io/ByteSource.java new file mode 100644 index 000000000000..d7afde774f8c --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/io/ByteSource.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2012 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.common.io; +import com.google.common.base.Optional; +import com.google.common.hash.HashCode; +import com.google.common.hash.HashFunction; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.Charset; +import java.util.Iterator; + +public abstract class ByteSource { + public CharSource asCharSource(Charset charset) { + return null; + } + + public abstract InputStream openStream() throws IOException; + + public InputStream openBufferedStream() throws IOException { + return null; + } + + public ByteSource slice(long offset, long length) { + return null; + } + + public boolean isEmpty() throws IOException { + return false; + } + + public Optional sizeIfKnown() { + return null; + } + + public long size() throws IOException { + return 0; + } + + public long copyTo(OutputStream output) throws IOException { + return 0; + } + + public long copyTo(ByteSink sink) throws IOException { + return 0; + } + + public byte[] read() throws IOException { + return null; + } + + public T read(ByteProcessor processor) throws IOException { + return null; + } + + public HashCode hash(HashFunction hashFunction) throws IOException { + return null; + } + + public boolean contentEquals(ByteSource other) throws IOException { + return false; + } + + public static ByteSource concat(Iterable sources) { + return null; + } + + public static ByteSource concat(Iterator sources) { + return null; + } + + public static ByteSource concat(ByteSource... sources) { + return null; + } + + public static ByteSource wrap(byte[] b) { + return null; + } + + public static ByteSource empty() { + return null; + } + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/io/ByteStreams.java b/java/ql/test/stubs/guava-30.0/com/google/common/io/ByteStreams.java new file mode 100644 index 000000000000..55d313c1a5cc --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/io/ByteStreams.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2007 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.common.io; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; + +public final class ByteStreams { + public static long copy(InputStream from, OutputStream to) throws IOException { + return 0; + } + + public static long copy(ReadableByteChannel from, WritableByteChannel to) throws IOException { + return 0; + } + + public static byte[] toByteArray(InputStream in) throws IOException { + return null; + } + + public static long exhaust(InputStream in) throws IOException { + return 0; + } + + public static ByteArrayDataInput newDataInput(byte[] bytes) { + return null; + } + + public static ByteArrayDataInput newDataInput(byte[] bytes, int start) { + return null; + } + + public static ByteArrayDataInput newDataInput(ByteArrayInputStream byteArrayInputStream) { + return null; + } + + public static ByteArrayDataOutput newDataOutput() { + return null; + } + + public static ByteArrayDataOutput newDataOutput(int size) { + return null; + } + + public static ByteArrayDataOutput newDataOutput(ByteArrayOutputStream byteArrayOutputStream) { + return null; + } + + public static OutputStream nullOutputStream() { + return null; + } + + public static InputStream limit(InputStream in, long limit) { + return null; + } + + public static void readFully(InputStream in, byte[] b) throws IOException { + } + + public static void readFully(InputStream in, byte[] b, int off, int len) throws IOException { + } + + public static void skipFully(InputStream in, long n) throws IOException { + } + + public static T readBytes(InputStream input, ByteProcessor processor) throws IOException { + return null; + } + + public static int read(InputStream in, byte[] b, int off, int len) throws IOException { + return 0; + } + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/io/CharSink.java b/java/ql/test/stubs/guava-30.0/com/google/common/io/CharSink.java new file mode 100644 index 000000000000..a9e09d263628 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/io/CharSink.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2012 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.common.io; +import java.io.IOException; +import java.io.Writer; +import java.util.stream.Stream; + +public abstract class CharSink { + public abstract Writer openStream() throws IOException; + + public Writer openBufferedStream() throws IOException { + return null; + } + + public void write(CharSequence charSequence) throws IOException { + } + + public void writeLines(Iterable lines) throws IOException { + } + + public void writeLines(Iterable lines, String lineSeparator) + throws IOException { + } + + public void writeLines(Stream lines) throws IOException { + } + + public void writeLines(Stream lines, String lineSeparator) + throws IOException { + } + + public long writeFrom(Readable readable) throws IOException { + return 0; + } + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/io/CharSource.java b/java/ql/test/stubs/guava-30.0/com/google/common/io/CharSource.java new file mode 100644 index 000000000000..cbe01e862083 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/io/CharSource.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2012 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.common.io; +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableList; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.Reader; +import java.nio.charset.Charset; +import java.util.Iterator; +import java.util.function.Consumer; +import java.util.stream.Stream; +import org.checkerframework.checker.nullness.qual.Nullable; + +public abstract class CharSource { + public ByteSource asByteSource(Charset charset) { + return null; + } + + public abstract Reader openStream() throws IOException; + + public BufferedReader openBufferedStream() throws IOException { + return null; + } + + public Stream lines() throws IOException { + return null; + } + + public Optional lengthIfKnown() { + return null; + } + + public long length() throws IOException { + return 0; + } + + public long copyTo(Appendable appendable) throws IOException { + return 0; + } + + public long copyTo(CharSink sink) throws IOException { + return 0; + } + + public String read() throws IOException { + return null; + } + + public @Nullable String readFirstLine() throws IOException { + return null; + } + + public ImmutableList readLines() throws IOException { + return null; + } + + public T readLines(LineProcessor processor) throws IOException { + return null; + } + + public void forEachLine(Consumer action) throws IOException { + } + + public boolean isEmpty() throws IOException { + return false; + } + + public static CharSource concat(Iterable sources) { + return null; + } + + public static CharSource concat(Iterator sources) { + return null; + } + + public static CharSource concat(CharSource... sources) { + return null; + } + + public static CharSource wrap(CharSequence charSequence) { + return null; + } + + public static CharSource empty() { + return null; + } + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/io/CharStreams.java b/java/ql/test/stubs/guava-30.0/com/google/common/io/CharStreams.java new file mode 100644 index 000000000000..6de37d4cf870 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/io/CharStreams.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2007 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.common.io; +import java.io.IOException; +import java.io.Reader; +import java.io.Writer; +import java.util.List; + +public final class CharStreams { + public static long copy(Readable from, Appendable to) throws IOException { + return 0; + } + + public static String toString(Readable r) throws IOException { + return null; + } + + public static List readLines(Readable r) throws IOException { + return null; + } + + public static T readLines(Readable readable, LineProcessor processor) throws IOException { + return null; + } + + public static long exhaust(Readable readable) throws IOException { + return 0; + } + + public static void skipFully(Reader reader, long n) throws IOException { + } + + public static Writer nullWriter() { + return null; + } + + public static Writer asWriter(Appendable target) { + return null; + } + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/io/Closer.java b/java/ql/test/stubs/guava-30.0/com/google/common/io/Closer.java new file mode 100644 index 000000000000..d15ff355713b --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/io/Closer.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2012 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.common.io; +import java.io.Closeable; +import java.io.IOException; +import org.checkerframework.checker.nullness.qual.Nullable; + +public final class Closer implements Closeable { + public static Closer create() { + return null; + } + + public C register(@Nullable C closeable) { + return null; + } + + public RuntimeException rethrow(Throwable e) throws IOException { + return null; + } + + public RuntimeException rethrow(Throwable e, Class declaredType) + throws IOException, X { + return null; + } + + public RuntimeException rethrow( + Throwable e, Class declaredType1, Class declaredType2) throws IOException, X1, X2 { + return null; + } + + @Override + public void close() throws IOException { + } + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/io/FileWriteMode.java b/java/ql/test/stubs/guava-30.0/com/google/common/io/FileWriteMode.java new file mode 100644 index 000000000000..b62e3aa72f2f --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/io/FileWriteMode.java @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2012 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.common.io; + +public enum FileWriteMode { +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/io/Files.java b/java/ql/test/stubs/guava-30.0/com/google/common/io/Files.java new file mode 100644 index 000000000000..f2519d6b146c --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/io/Files.java @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2007 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.common.io; +import com.google.common.base.Predicate; +import com.google.common.graph.Traverser; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.MappedByteBuffer; +import java.nio.channels.FileChannel.MapMode; +import java.nio.charset.Charset; +import java.util.List; + +public final class Files { + public static BufferedReader newReader(File file, Charset charset) throws FileNotFoundException { + return null; + } + + public static BufferedWriter newWriter(File file, Charset charset) throws FileNotFoundException { + return null; + } + + public static ByteSource asByteSource(File file) { + return null; + } + + public static ByteSink asByteSink(File file, FileWriteMode... modes) { + return null; + } + + public static CharSource asCharSource(File file, Charset charset) { + return null; + } + + public static CharSink asCharSink(File file, Charset charset, FileWriteMode... modes) { + return null; + } + + public static byte[] toByteArray(File file) throws IOException { + return null; + } + + public static String toString(File file, Charset charset) throws IOException { + return null; + } + + public static void write(byte[] from, File to) throws IOException { + } + + public static void write(CharSequence from, File to, Charset charset) throws IOException { + } + + public static void copy(File from, OutputStream to) throws IOException { + } + + public static void copy(File from, File to) throws IOException { + } + + public static boolean equal(File file1, File file2) throws IOException { + return false; + } + + public static File createTempDir() { + return null; + } + + public static void touch(File file) throws IOException { + } + + public static void createParentDirs(File file) throws IOException { + } + + public static void move(File from, File to) throws IOException { + } + + public static List readLines(File file, Charset charset) throws IOException { + return null; + } + + public static MappedByteBuffer map(File file) throws IOException { + return null; + } + + public static MappedByteBuffer map(File file, MapMode mode) throws IOException { + return null; + } + + public static MappedByteBuffer map(File file, MapMode mode, long size) throws IOException { + return null; + } + + public static String simplifyPath(String pathname) { + return null; + } + + public static String getFileExtension(String fullName) { + return null; + } + + public static String getNameWithoutExtension(String file) { + return null; + } + + public static Traverser fileTraverser() { + return null; + } + + public static Predicate isDirectory() { + return null; + } + + public static Predicate isFile() { + return null; + } + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/io/LineProcessor.java b/java/ql/test/stubs/guava-30.0/com/google/common/io/LineProcessor.java new file mode 100644 index 000000000000..c5dfe2c02c2d --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/io/LineProcessor.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2009 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.common.io; +import java.io.IOException; + +public interface LineProcessor { + boolean processLine(String line) throws IOException; + + T getResult(); + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/io/LineReader.java b/java/ql/test/stubs/guava-30.0/com/google/common/io/LineReader.java new file mode 100644 index 000000000000..30a4d1f03cdd --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/io/LineReader.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2007 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.common.io; +import java.io.IOException; + +public final class LineReader { + public LineReader(Readable readable) { + } + + public String readLine() throws IOException { + return null; + } + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/io/MoreFiles.java b/java/ql/test/stubs/guava-30.0/com/google/common/io/MoreFiles.java new file mode 100644 index 000000000000..46f3080409a8 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/io/MoreFiles.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2013 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.common.io; +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableList; +import com.google.common.graph.Traverser; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.LinkOption; +import java.nio.file.OpenOption; +import java.nio.file.Path; +import java.nio.file.attribute.FileAttribute; + +public final class MoreFiles { + public static ByteSource asByteSource(Path path, OpenOption... options) { + return null; + } + + public static ByteSink asByteSink(Path path, OpenOption... options) { + return null; + } + + public static CharSource asCharSource(Path path, Charset charset, OpenOption... options) { + return null; + } + + public static CharSink asCharSink(Path path, Charset charset, OpenOption... options) { + return null; + } + + public static ImmutableList listFiles(Path dir) throws IOException { + return null; + } + + public static Traverser fileTraverser() { + return null; + } + + public static Predicate isDirectory(LinkOption... options) { + return null; + } + + public static Predicate isRegularFile(LinkOption... options) { + return null; + } + + public static boolean equal(Path path1, Path path2) throws IOException { + return false; + } + + public static void touch(Path path) throws IOException { + } + + public static void createParentDirectories(Path path, FileAttribute... attrs) + throws IOException { + } + + public static String getFileExtension(Path path) { + return null; + } + + public static String getNameWithoutExtension(Path path) { + return null; + } + + public static void deleteRecursively(Path path, RecursiveDeleteOption... options) + throws IOException { + } + + public static void deleteDirectoryContents(Path path, RecursiveDeleteOption... options) + throws IOException { + } + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/io/RecursiveDeleteOption.java b/java/ql/test/stubs/guava-30.0/com/google/common/io/RecursiveDeleteOption.java new file mode 100644 index 000000000000..ed0168b7ef5f --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/io/RecursiveDeleteOption.java @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2014 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.common.io; + +public enum RecursiveDeleteOption { +} diff --git a/java/ql/test/stubs/guava-30.0/org/checkerframework/checker/nullness/qual/Nullable.java b/java/ql/test/stubs/guava-30.0/org/checkerframework/checker/nullness/qual/Nullable.java new file mode 100644 index 000000000000..b2943cd96b6d --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/org/checkerframework/checker/nullness/qual/Nullable.java @@ -0,0 +1,2 @@ +package org.checkerframework.checker.nullness.qual; +public @interface Nullable {} \ No newline at end of file From d30d1a2ab20c98270cc70a381ff90ab54705f6f9 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Tue, 2 Mar 2021 17:12:48 +0000 Subject: [PATCH 04/12] Add unit tests and fix issues --- .../code/java/dataflow/ExternalFlow.qll | 1 + .../code/java/frameworks/guava/Guava.qll | 1 + .../semmle/code/java/frameworks/guava/IO.qll | 24 +++- .../frameworks/guava/TestCollect.java | 4 +- .../frameworks/guava/TestIO.java | 116 ++++++++++++++++++ .../google/common/io/CountingInputStream.java | 52 ++++++++ .../io/LittleEndianDataInputStream.java | 99 +++++++++++++++ 7 files changed, 289 insertions(+), 8 deletions(-) create mode 100644 java/ql/test/library-tests/frameworks/guava/TestIO.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/io/CountingInputStream.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/io/LittleEndianDataInputStream.java diff --git a/java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll b/java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll index f5fbad778fb2..7197caea3514 100644 --- a/java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll +++ b/java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll @@ -71,6 +71,7 @@ private import internal.DataFlowPrivate private module Frameworks { private import semmle.code.java.frameworks.ApacheHttp private import semmle.code.java.frameworks.apache.Lang + private import semmle.code.java.frameworks.guava.Guava } private predicate sourceModelCsv(string row) { diff --git a/java/ql/src/semmle/code/java/frameworks/guava/Guava.qll b/java/ql/src/semmle/code/java/frameworks/guava/Guava.qll index c6bdf0ea9b94..63e612d62abf 100644 --- a/java/ql/src/semmle/code/java/frameworks/guava/Guava.qll +++ b/java/ql/src/semmle/code/java/frameworks/guava/Guava.qll @@ -6,3 +6,4 @@ import java import StringUtils import Collections import Preconditions +import IO diff --git a/java/ql/src/semmle/code/java/frameworks/guava/IO.qll b/java/ql/src/semmle/code/java/frameworks/guava/IO.qll index ae9a90479b2d..fadf283d22b4 100644 --- a/java/ql/src/semmle/code/java/frameworks/guava/IO.qll +++ b/java/ql/src/semmle/code/java/frameworks/guava/IO.qll @@ -14,7 +14,17 @@ private class GuavaIoCsv extends SummaryModelCsv { "com.google.common.io;BaseEncoding;true;decodingSource;(CharSource);;Argument[0];ReturnValue;taint", "com.google.common.io;BaseEncoding;true;encode;(byte[]);;Argument[0];ReturnValue;taint", "com.google.common.io;BaseEncoding;true;encode;(byte[],int,int);;Argument[0];ReturnValue;taint", - "com.google.common.io;ByteSource;true;asCharSource;(Charset);;Argument[0];ReturnValue;taint", + "com.google.common.io;BaseEncoding;true;withSeparator;(String,int);;Argument[0];ReturnValue;taint", + "com.google.common.io;BaseEncoding;true;decode;(CharSequence);;Argument[-1];ReturnValue;taint", + "com.google.common.io;BaseEncoding;true;decodingStream;(Reader);;Argument[-1];ReturnValue;taint", + "com.google.common.io;BaseEncoding;true;decodingSource;(CharSource);;Argument[-1];ReturnValue;taint", + "com.google.common.io;BaseEncoding;true;encode;(byte[]);;Argument[-1];ReturnValue;taint", + "com.google.common.io;BaseEncoding;true;upperCase;();;Argument[-1];ReturnValue;taint", + "com.google.common.io;BaseEncoding;true;lowerCase;();;Argument[-1];ReturnValue;taint", + "com.google.common.io;BaseEncoding;true;withPadChar;(char);;Argument[-1];ReturnValue;taint", + "com.google.common.io;BaseEncoding;true;omitPadding;();;Argument[-1];ReturnValue;taint", + "com.google.common.io;BaseEncoding;true;encode;(byte[],int,int);;Argument[-1];ReturnValue;taint", + "com.google.common.io;ByteSource;true;asCharSource;(Charset);;Argument[-1];ReturnValue;taint", "com.google.common.io;ByteSource;true;concat;;;Argument[0];ReturnValue;taint", "com.google.common.io;ByteSource;true;openStream;();;Argument[-1];ReturnValue;taint", "com.google.common.io;ByteSource;true;openBufferedStream;();;Argument[-1];ReturnValue;taint", @@ -22,15 +32,16 @@ private class GuavaIoCsv extends SummaryModelCsv { "com.google.common.io;ByteSource;true;slice;(long,long);;Argument[-1];ReturnValue;taint", "com.google.common.io;ByteSource;true;wrap;(byte[]);;Argument[0];ReturnValue;taint", "com.google.common.io;ByteStreams;false;copy;(InputStream,OutputStream);;Argument[0];Argument[1];taint", + "com.google.common.io;ByteStreams;false;copy;(ReadablyByteChannel,WritableByteChannel);;Argument[0];Argument[1];taint", "com.google.common.io;ByteStreams;false;limit;(InputStream,long);;Argument[0];ReturnValue;taint", "com.google.common.io;ByteStreams;false;newDataInput;(byte[]);;Argument[0];ReturnValue;taint", "com.google.common.io;ByteStreams;false;newDataInput;(byte[],int);;Argument[0];ReturnValue;taint", "com.google.common.io;ByteStreams;false;newDataInput;(ByteArrayInputStream);;Argument[0];ReturnValue;taint", - "com.google.common.io;ByteStreams;false;read;(InputStream,byte[],int,int);;Argument[0];Argument[-1];taint", + "com.google.common.io;ByteStreams;false;read;(InputStream,byte[],int,int);;Argument[0];Argument[1];taint", "com.google.common.io;ByteStreams;false;readFully;(InputStream,byte[]);;Argument[0];Argument[1];taint", "com.google.common.io;ByteStreams;false;readFully;(InputStream,byte[],int,int);;Argument[0];Argument[1];taint", "com.google.common.io;ByteStreams;false;toByteArray;(InputStream);;Argument[0];ReturnValue;taint", - "com.google.common.io;CharSource;true;asByteSource;(Charset);;Argument[0];ReturnValue;taint", + "com.google.common.io;CharSource;true;asByteSource;(Charset);;Argument[-1];ReturnValue;taint", "com.google.common.io;CharSource;true;concat;;;Argument[0];ReturnValue;taint", "com.google.common.io;CharSource;true;copyTo;(Appendable);;Argument[-1];Argument[0];taint", "com.google.common.io;CharSource;true;openStream;();;Argument[-1];ReturnValue;taint", @@ -38,9 +49,10 @@ private class GuavaIoCsv extends SummaryModelCsv { "com.google.common.io;CharSource;true;read;();;Argument[-1];ReturnValue;taint", "com.google.common.io;CharSource;true;readFirstLine;();;Argument[-1];ReturnValue;taint", "com.google.common.io;CharSource;true;readLines;();;Argument[-1];ReturnValue;taint", + "com.google.common.io;CharSource;true;lines;();;Argument[-1];ReturnValue;taint", "com.google.common.io;CharSource;true;wrap;(CharSequence);;Argument[0];ReturnValue;taint", "com.google.common.io;CharStreams;false;copy;(Readable,Appendable);;Argument[0];Argument[1];taint", - "com.google.common.io;CharStreams;false;readLines;(Readable);;Argument[0];Argument[-1];taint", + "com.google.common.io;CharStreams;false;readLines;(Readable);;Argument[0];ReturnValue;taint", "com.google.common.io;CharStreams;false;toString;(Readable);;Argument[0];ReturnValue;taint", "com.google.common.io;Closer;true;register;;;Argument[0];ReturnValue;value", "com.google.common.io;Files;false;getFileExtension;(String);;Argument[0];ReturnValue;taint", @@ -48,8 +60,8 @@ private class GuavaIoCsv extends SummaryModelCsv { "com.google.common.io;Files;false;simplifyPath;(String);;Argument[0];ReturnValue;taint", "com.google.common.io;MoreFiles;false;getFileExtension;(Path);;Argument[0];ReturnValue;taint", "com.google.common.io;MoreFiles;false;getNameWithoutExtension;(Path);;Argument[0];ReturnValue;taint", - "com.google.common.io;LineReader;false;LineReader;(Reader);;Argument[0];ReturnValue;taint", - "com.google.common.io;LineReader;false;readLine;();;Argument[-1];ReturnValue;taint" + "com.google.common.io;LineReader;false;LineReader;(Readable);;Argument[0];ReturnValue;taint", + "com.google.common.io;LineReader;true;readLine;();;Argument[-1];ReturnValue;taint" ] } } diff --git a/java/ql/test/library-tests/frameworks/guava/TestCollect.java b/java/ql/test/library-tests/frameworks/guava/TestCollect.java index 382b2de64cbd..3b43a73e6c64 100644 --- a/java/ql/test/library-tests/frameworks/guava/TestCollect.java +++ b/java/ql/test/library-tests/frameworks/guava/TestCollect.java @@ -72,7 +72,7 @@ void test4(Table t1, Table t2, T sink(t1.remove("r", "c")); // $numTaintFlow=1 t3.row("r").put("c", x); - sink(t3); // MISSING:$numTaintFlow=1 + sink(t3); // $ MISSING:numTaintFlow=1 } void test4(Multimap m1, Multimap m2, Multimap m3, @@ -94,7 +94,7 @@ void test4(Multimap m1, Multimap m2, Multimap comp, SortedSet sorS, SortedMap sorM) { diff --git a/java/ql/test/library-tests/frameworks/guava/TestIO.java b/java/ql/test/library-tests/frameworks/guava/TestIO.java new file mode 100644 index 000000000000..797e17009130 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/guava/TestIO.java @@ -0,0 +1,116 @@ +package com.google.common.io; + +import com.google.common.collect.ImmutableList; +import java.io.InputStreamReader; +import java.io.Reader; +import java.lang.StringBuffer; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.Closeable; +import java.nio.file.Path; +import java.io.IOException; + +class TestIO { + Object taint() { return null; } + String staint(){ return (String) taint(); } + byte[] btaint() { return (byte[]) taint(); } + InputStream itaint() { return (InputStream) taint(); } + Reader rtaint() { return new InputStreamReader(itaint()); } + Path ptaint() { return (Path) taint(); } + + void sink(Object o) {} + + void test1() { + BaseEncoding enc = BaseEncoding.base64(); + sink(enc.decode(staint())); // $numTaintFlow=1 + sink(enc.encode(btaint())); // $numTaintFlow=1 + sink(enc.encode(btaint(), 0, 42)); // $numTaintFlow=1 + sink(enc.decodingStream(rtaint())); // $numTaintFlow=1 + sink(enc.decodingSource(CharSource.wrap(staint()))); // $numTaintFlow=1 + sink(enc.withSeparator(staint(), 10).omitPadding().lowerCase().decode("abc")); // $numTaintFlow=1 + } + + void test2() throws IOException { + ByteSource b = ByteSource.wrap(btaint()); + sink(b.openStream()); // $numTaintFlow=1 + sink(b.openBufferedStream()); // $numTaintFlow=1 + sink(b.asCharSource(null)); // $numTaintFlow=1 + sink(b.slice(42,1337)); // $numTaintFlow=1 + sink(b.read()); // $numTaintFlow=1 + sink(ByteSource.concat(ByteSource.empty(), ByteSource.empty(), b)); // $numTaintFlow=1 + sink(ByteSource.concat(ImmutableList.of(ByteSource.empty(), ByteSource.empty(), b))); // $numTaintFlow=1 + sink(b.read(new MyByteProcessor())); // $ MISSING:numTaintFlow=1 + + CharSource c = CharSource.wrap(staint()); + sink(c.openStream()); // $numTaintFlow=1 + sink(c.openBufferedStream()); // $numTaintFlow=1 + sink(c.asByteSource(null)); // $numTaintFlow=1 + sink(c.readFirstLine()); // $numTaintFlow=1 + sink(c.readLines()); // $numTaintFlow=1 + sink(c.read()); // $numTaintFlow=1 + sink(c.lines()); // $numTaintFlow=1 + sink(CharSource.concat(CharSource.empty(), CharSource.empty(), c)); // $numTaintFlow=1 + sink(CharSource.concat(ImmutableList.of(CharSource.empty(), CharSource.empty(), c))); // $numTaintFlow=1 + sink(c.readLines(new MyLineProcessor())); // $ MISSING:numTaintFlow=1 + c.forEachLine(l -> sink(l)); // $ MISSING:numTaintFlow=1 + StringBuffer buf = new StringBuffer(); + c.copyTo(buf); + sink(buf); // $numTaintFlow=1 + } + + class MyByteProcessor implements ByteProcessor { + byte[] buf; + public Object getResult() { return buf; } + public boolean processBytes(byte[] b, int off, int len) { this.buf = b; return false; } + } + + class MyLineProcessor implements LineProcessor { + String s = ""; + public String getResult() { return s; } + public boolean processLine(String l) { this.s += l; return true; } + } + + void test3() throws IOException { + sink(ByteStreams.limit(itaint(), 1337)); // $numTaintFlow=1 + sink(ByteStreams.newDataInput(btaint())); // $numTaintFlow=1 + sink(ByteStreams.newDataInput(btaint(), 0)); // $numTaintFlow=1 + sink(ByteStreams.newDataInput(btaint())); // $numTaintFlow=1 + sink(ByteStreams.newDataInput(btaint()).readLine()); // $ MISSING:numTaintFlow=1 + sink(ByteStreams.newDataInput(new ByteArrayInputStream(btaint()))); // $numTaintFlow=1 + byte[] b1 = null, b2 = null, b3 = null; + ByteStreams.read(itaint(), b1, 0, 42); + sink(b1); // $numTaintFlow=1 + ByteStreams.readFully(itaint(), b2); + sink(b2); // $numTaintFlow=1 + ByteStreams.readFully(itaint(), b3, 0, 42); + sink(b3); // $numTaintFlow=1 + sink(ByteStreams.readBytes(itaint(), new MyByteProcessor())); // $ MISSING:numTaintFlow=1 + sink(ByteStreams.toByteArray(itaint())); // $numTaintFlow=1 + + StringBuffer buf = new StringBuffer(); + CharStreams.copy(rtaint(), buf); + sink(buf); // $numTaintFlow=1 + sink(CharStreams.readLines(rtaint())); // $numTaintFlow=1 + sink(CharStreams.readLines(rtaint(), new MyLineProcessor())); // $ MISSING:numTaintFlow=1 + sink(CharStreams.toString(rtaint())); // $numTaintFlow=1 + } + + void test4() throws IOException { + sink(Closer.create().register((Closeable) taint())); // $numTaintFlow=1 + sink(new LineReader(rtaint()).readLine()); // $numTaintFlow=1 + sink(Files.simplifyPath(staint())); // $numTaintFlow=1 + sink(Files.getFileExtension(staint())); // $numTaintFlow=1 + sink(Files.getNameWithoutExtension(staint())); // $numTaintFlow=1 + sink(MoreFiles.getFileExtension(ptaint())); // $numTaintFlow=1 + sink(MoreFiles.getNameWithoutExtension(ptaint())); // $numTaintFlow=1 + } + + void test6() throws IOException { + sink(new CountingInputStream(itaint())); // $numTaintFlow=1 + byte[] buf = null; + new CountingInputStream(itaint()).read(buf, 0, 42); + sink(buf); // $numTaintFlow=1 + sink(new LittleEndianDataInputStream(itaint())); // $numTaintFlow=1 + sink(new LittleEndianDataInputStream(itaint()).readUTF()); // $ MISSING:numTaintFlow=1 + } +} \ No newline at end of file diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/io/CountingInputStream.java b/java/ql/test/stubs/guava-30.0/com/google/common/io/CountingInputStream.java new file mode 100644 index 000000000000..5c60dc434d86 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/io/CountingInputStream.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2007 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.common.io; +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; + +public final class CountingInputStream extends FilterInputStream { + public CountingInputStream(InputStream in) { + super(in); + } + + public long getCount() { + return 0; + } + + @Override + public int read() throws IOException { + return 0; + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + return 0; + } + + @Override + public long skip(long n) throws IOException { + return 0; + } + + @Override + public synchronized void mark(int readlimit) { + } + + @Override + public synchronized void reset() throws IOException { + } + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/io/LittleEndianDataInputStream.java b/java/ql/test/stubs/guava-30.0/com/google/common/io/LittleEndianDataInputStream.java new file mode 100644 index 000000000000..755633634bdd --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/io/LittleEndianDataInputStream.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2007 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.common.io; +import java.io.DataInput; +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; + +public final class LittleEndianDataInputStream extends FilterInputStream implements DataInput { + public LittleEndianDataInputStream(InputStream in) { + super(in); + } + + @Override + public String readLine() { + return null; + } + + @Override + public void readFully(byte[] b) throws IOException { + } + + @Override + public void readFully(byte[] b, int off, int len) throws IOException { + } + + @Override + public int skipBytes(int n) throws IOException { + return 0; + } + + @Override + public int readUnsignedByte() throws IOException { + return 0; + } + + @Override + public int readUnsignedShort() throws IOException { + return 0; + } + + @Override + public int readInt() throws IOException { + return 0; + } + + @Override + public long readLong() throws IOException { + return 0; + } + + @Override + public float readFloat() throws IOException { + return 0; + } + + @Override + public double readDouble() throws IOException { + return 0; + } + + @Override + public String readUTF() throws IOException { + return null; + } + + @Override + public short readShort() throws IOException { + return 0; + } + + @Override + public char readChar() throws IOException { + return '0'; + } + + @Override + public byte readByte() throws IOException { + return 0; + } + + @Override + public boolean readBoolean() throws IOException { + return false; + } + +} From e916e04fe1fd94d7135617f4b3f05bb06a474e37 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Tue, 2 Mar 2021 17:50:41 +0000 Subject: [PATCH 05/12] Add change note --- java/change-notes/2021-03-02-guava-io | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 java/change-notes/2021-03-02-guava-io diff --git a/java/change-notes/2021-03-02-guava-io b/java/change-notes/2021-03-02-guava-io new file mode 100644 index 000000000000..888ab0d9364d --- /dev/null +++ b/java/change-notes/2021-03-02-guava-io @@ -0,0 +1,2 @@ +lgtm,codescanning +* Increased coverage of the Guava framework to include classes in the `com.google.common.io` package. \ No newline at end of file From 5278cc9e9edf8287a469754841a05af879d1faee Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Tue, 2 Mar 2021 17:52:46 +0000 Subject: [PATCH 06/12] Fix change note file extension --- java/change-notes/{2021-03-02-guava-io => 2021-03-02-guava-io.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename java/change-notes/{2021-03-02-guava-io => 2021-03-02-guava-io.md} (100%) diff --git a/java/change-notes/2021-03-02-guava-io b/java/change-notes/2021-03-02-guava-io.md similarity index 100% rename from java/change-notes/2021-03-02-guava-io rename to java/change-notes/2021-03-02-guava-io.md From f5564b1c3befb41e561df5df260750f430ac93b7 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Wed, 3 Mar 2021 15:35:58 +0000 Subject: [PATCH 07/12] Remove unnecassary import --- java/ql/src/semmle/code/java/frameworks/guava/IO.qll | 1 - 1 file changed, 1 deletion(-) diff --git a/java/ql/src/semmle/code/java/frameworks/guava/IO.qll b/java/ql/src/semmle/code/java/frameworks/guava/IO.qll index fadf283d22b4..2583c1edf0c9 100644 --- a/java/ql/src/semmle/code/java/frameworks/guava/IO.qll +++ b/java/ql/src/semmle/code/java/frameworks/guava/IO.qll @@ -1,7 +1,6 @@ /** Definitions of taint steps in the IO packae of the Guava framework */ import java -private import semmle.code.java.dataflow.DataFlow private import semmle.code.java.dataflow.ExternalFlow private class GuavaIoCsv extends SummaryModelCsv { From 61dcf3a2759775083a3fdca28db2423a08adaa2d Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Thu, 4 Mar 2021 12:24:34 +0000 Subject: [PATCH 08/12] Apply suggestions from code review Co-authored-by: Marcono1234 --- java/change-notes/2021-03-02-guava-io.md | 2 +- java/ql/src/semmle/code/java/frameworks/guava/IO.qll | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java/change-notes/2021-03-02-guava-io.md b/java/change-notes/2021-03-02-guava-io.md index 888ab0d9364d..fb16677d8e78 100644 --- a/java/change-notes/2021-03-02-guava-io.md +++ b/java/change-notes/2021-03-02-guava-io.md @@ -1,2 +1,2 @@ lgtm,codescanning -* Increased coverage of the Guava framework to include classes in the `com.google.common.io` package. \ No newline at end of file +* Increased coverage of the Guava framework by including classes in the `com.google.common.io` package. diff --git a/java/ql/src/semmle/code/java/frameworks/guava/IO.qll b/java/ql/src/semmle/code/java/frameworks/guava/IO.qll index 2583c1edf0c9..8d8dc2b8ebf7 100644 --- a/java/ql/src/semmle/code/java/frameworks/guava/IO.qll +++ b/java/ql/src/semmle/code/java/frameworks/guava/IO.qll @@ -1,4 +1,4 @@ -/** Definitions of taint steps in the IO packae of the Guava framework */ +/** Definitions of taint steps in the IO package of the Guava framework */ import java private import semmle.code.java.dataflow.ExternalFlow From 470a2ca336be525536d4ae45cd066c2a511340ea Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Thu, 4 Mar 2021 12:53:23 +0000 Subject: [PATCH 09/12] Add CopyTo --- java/ql/src/semmle/code/java/frameworks/guava/IO.qll | 1 + java/ql/test/library-tests/frameworks/guava/TestIO.java | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/java/ql/src/semmle/code/java/frameworks/guava/IO.qll b/java/ql/src/semmle/code/java/frameworks/guava/IO.qll index 8d8dc2b8ebf7..9fe05fa63769 100644 --- a/java/ql/src/semmle/code/java/frameworks/guava/IO.qll +++ b/java/ql/src/semmle/code/java/frameworks/guava/IO.qll @@ -25,6 +25,7 @@ private class GuavaIoCsv extends SummaryModelCsv { "com.google.common.io;BaseEncoding;true;encode;(byte[],int,int);;Argument[-1];ReturnValue;taint", "com.google.common.io;ByteSource;true;asCharSource;(Charset);;Argument[-1];ReturnValue;taint", "com.google.common.io;ByteSource;true;concat;;;Argument[0];ReturnValue;taint", + "com.google.common.io;ByteSource;true;copyTo;(OutputStream);;Argument[-1];Argument[0];taint", "com.google.common.io;ByteSource;true;openStream;();;Argument[-1];ReturnValue;taint", "com.google.common.io;ByteSource;true;openBufferedStream;();;Argument[-1];ReturnValue;taint", "com.google.common.io;ByteSource;true;read;();;Argument[-1];ReturnValue;taint", diff --git a/java/ql/test/library-tests/frameworks/guava/TestIO.java b/java/ql/test/library-tests/frameworks/guava/TestIO.java index 797e17009130..6d333b4ca2ba 100644 --- a/java/ql/test/library-tests/frameworks/guava/TestIO.java +++ b/java/ql/test/library-tests/frameworks/guava/TestIO.java @@ -5,6 +5,7 @@ import java.io.Reader; import java.lang.StringBuffer; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.Closeable; import java.nio.file.Path; @@ -40,6 +41,9 @@ void test2() throws IOException { sink(ByteSource.concat(ByteSource.empty(), ByteSource.empty(), b)); // $numTaintFlow=1 sink(ByteSource.concat(ImmutableList.of(ByteSource.empty(), ByteSource.empty(), b))); // $numTaintFlow=1 sink(b.read(new MyByteProcessor())); // $ MISSING:numTaintFlow=1 + ByteArrayOutputStream out = new ByteArrayOutputStream(); + b.copyTo(out); + sink(out.toByteArray()); // $numTaintFlow=1 CharSource c = CharSource.wrap(staint()); sink(c.openStream()); // $numTaintFlow=1 From 3f3640fcbde8835cede501fef6658c8698b09ae5 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Thu, 4 Mar 2021 14:23:45 +0000 Subject: [PATCH 10/12] Model ByteArrayDataOutput --- .../semmle/code/java/frameworks/guava/IO.qll | 17 ++++++++++++++++- .../library-tests/frameworks/guava/TestIO.java | 6 ++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/java/ql/src/semmle/code/java/frameworks/guava/IO.qll b/java/ql/src/semmle/code/java/frameworks/guava/IO.qll index 9fe05fa63769..6b926932641e 100644 --- a/java/ql/src/semmle/code/java/frameworks/guava/IO.qll +++ b/java/ql/src/semmle/code/java/frameworks/guava/IO.qll @@ -37,6 +37,7 @@ private class GuavaIoCsv extends SummaryModelCsv { "com.google.common.io;ByteStreams;false;newDataInput;(byte[]);;Argument[0];ReturnValue;taint", "com.google.common.io;ByteStreams;false;newDataInput;(byte[],int);;Argument[0];ReturnValue;taint", "com.google.common.io;ByteStreams;false;newDataInput;(ByteArrayInputStream);;Argument[0];ReturnValue;taint", + "com.google.common.io;ByteStreams;false;newDataOutput;(ByteArrayOutputStream);;Argument[0];ReturnValue;taint", "com.google.common.io;ByteStreams;false;read;(InputStream,byte[],int,int);;Argument[0];Argument[1];taint", "com.google.common.io;ByteStreams;false;readFully;(InputStream,byte[]);;Argument[0];Argument[1];taint", "com.google.common.io;ByteStreams;false;readFully;(InputStream,byte[],int,int);;Argument[0];Argument[1];taint", @@ -61,7 +62,21 @@ private class GuavaIoCsv extends SummaryModelCsv { "com.google.common.io;MoreFiles;false;getFileExtension;(Path);;Argument[0];ReturnValue;taint", "com.google.common.io;MoreFiles;false;getNameWithoutExtension;(Path);;Argument[0];ReturnValue;taint", "com.google.common.io;LineReader;false;LineReader;(Readable);;Argument[0];ReturnValue;taint", - "com.google.common.io;LineReader;true;readLine;();;Argument[-1];ReturnValue;taint" + "com.google.common.io;LineReader;true;readLine;();;Argument[-1];ReturnValue;taint", + "com.google.common.io;ByteArrayDataOutput;true;toByteArray;();;Argument[-1];ReturnValue;taint", + "com.google.common.io;ByteArrayDataOutput;true;write;(byte[]);;Argument[0];Argument[-1];taint", + "com.google.common.io;ByteArrayDataOutput;true;write;(byte[],int,int);;Argument[0];Argument[-1];taint", + "com.google.common.io;ByteArrayDataOutput;true;write;(int);;Argument[0];Argument[-1];taint", + "com.google.common.io;ByteArrayDataOutput;true;writeByte;(int);;Argument[0];Argument[-1];taint", + "com.google.common.io;ByteArrayDataOutput;true;writeBytes;(String);;Argument[0];Argument[-1];taint", + "com.google.common.io;ByteArrayDataOutput;true;writeChar;(int);;Argument[0];Argument[-1];taint", + "com.google.common.io;ByteArrayDataOutput;true;writeChars;(String);;Argument[0];Argument[-1];taint", + "com.google.common.io;ByteArrayDataOutput;true;writeDouble;(double);;Argument[0];Argument[-1];taint", + "com.google.common.io;ByteArrayDataOutput;true;writeFloat;(float);;Argument[0];Argument[-1];taint", + "com.google.common.io;ByteArrayDataOutput;true;writeInt;(int);;Argument[0];Argument[-1];taint", + "com.google.common.io;ByteArrayDataOutput;true;writeLong;(long);;Argument[0];Argument[-1];taint", + "com.google.common.io;ByteArrayDataOutput;true;writeShort;(int);;Argument[0];Argument[-1];taint", + "com.google.common.io;ByteArrayDataOutput;true;writeUTF;(String);;Argument[0];Argument[-1];taint" ] } } diff --git a/java/ql/test/library-tests/frameworks/guava/TestIO.java b/java/ql/test/library-tests/frameworks/guava/TestIO.java index 6d333b4ca2ba..685f18cc807b 100644 --- a/java/ql/test/library-tests/frameworks/guava/TestIO.java +++ b/java/ql/test/library-tests/frameworks/guava/TestIO.java @@ -81,6 +81,9 @@ void test3() throws IOException { sink(ByteStreams.newDataInput(btaint())); // $numTaintFlow=1 sink(ByteStreams.newDataInput(btaint()).readLine()); // $ MISSING:numTaintFlow=1 sink(ByteStreams.newDataInput(new ByteArrayInputStream(btaint()))); // $numTaintFlow=1 + ByteArrayOutputStream out = new ByteArrayOutputStream(); + out.write(btaint()); + sink(ByteStreams.newDataOutput(out)); // $numTaintFlow=1 byte[] b1 = null, b2 = null, b3 = null; ByteStreams.read(itaint(), b1, 0, 42); sink(b1); // $numTaintFlow=1 @@ -90,6 +93,9 @@ void test3() throws IOException { sink(b3); // $numTaintFlow=1 sink(ByteStreams.readBytes(itaint(), new MyByteProcessor())); // $ MISSING:numTaintFlow=1 sink(ByteStreams.toByteArray(itaint())); // $numTaintFlow=1 + ByteArrayDataOutput out2 = ByteStreams.newDataOutput(); + out2.writeUTF(staint()); + sink(out2.toByteArray()); // $numTaintFlow=1 StringBuffer buf = new StringBuffer(); CharStreams.copy(rtaint(), buf); From ed228cbcef55b0a81837e062bf499f84318f25f6 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Mon, 8 Mar 2021 14:07:53 +0000 Subject: [PATCH 11/12] Add sinks for URL Open Stream query --- .../Security/CWE/CWE-036/OpenStream.ql | 14 +++++++++----- .../src/semmle/code/java/frameworks/guava/IO.qll | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.ql b/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.ql index ab315277f2b4..d95b9d720033 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.ql @@ -8,6 +8,7 @@ import java import semmle.code.java.dataflow.TaintTracking import semmle.code.java.dataflow.FlowSources +import semmle.code.java.dataflow.ExternalFlow import DataFlow::PathGraph class URLConstructor extends ClassInstanceExpr { @@ -21,6 +22,13 @@ class URLConstructor extends ClassInstanceExpr { } } +class URLOpenStreamCsv extends SinkModelCsv { + override predicate row(string row) { + //"package;type;overrides;name;signature;ext;inputspec;kind", + row = "java.net;URL;true;openStream;();;Argument[-1];url-open-stream" + } +} + class URLOpenStreamMethod extends Method { URLOpenStreamMethod() { this.getDeclaringType() instanceof TypeUrl and @@ -33,11 +41,7 @@ class RemoteURLToOpenStreamFlowConfig extends TaintTracking::Configuration { override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } - override predicate isSink(DataFlow::Node sink) { - exists(MethodAccess m | - sink.asExpr() = m.getQualifier() and m.getMethod() instanceof URLOpenStreamMethod - ) - } + override predicate isSink(DataFlow::Node sink) { sinkNode(sink, "url-open-stream") } override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { exists(URLConstructor u | diff --git a/java/ql/src/semmle/code/java/frameworks/guava/IO.qll b/java/ql/src/semmle/code/java/frameworks/guava/IO.qll index 6b926932641e..2a4a03428083 100644 --- a/java/ql/src/semmle/code/java/frameworks/guava/IO.qll +++ b/java/ql/src/semmle/code/java/frameworks/guava/IO.qll @@ -80,3 +80,19 @@ private class GuavaIoCsv extends SummaryModelCsv { ] } } + +private class GuavaIoSinkCsv extends SinkModelCsv { + override predicate row(string row) { + row = + [ + //"package;type;overrides;name;signature;ext;inputspec;kind", + "com.google.common.io;Resources;false;asByteSource;(URL);;Argument[0];url-open-stream", + "com.google.common.io;Resources;false;asCharSource;(URL,Charset);;Argument[0];url-open-stream", + "com.google.common.io;Resources;false;copy;(URL,OutputStream);;Argument[0];url-open-stream", + "com.google.common.io;Resources;false;asByteSource;(URL);;Argument[0];url-open-stream", + "com.google.common.io;Resources;false;readLines;;;Argument[0];url-open-stream", + "com.google.common.io;Resources;false;toByteArray;(URL);;Argument[0];url-open-stream", + "com.google.common.io;Resources;false;toString;(URL,Charset);;Argument[0];url-open-stream" + ] + } +} From bd4a414abdc0049aa3cc47c71d1daede42006cb4 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Tue, 9 Mar 2021 10:50:15 +0000 Subject: [PATCH 12/12] Remove CSV data from query Co-authored-by: Anders Schack-Mulligen --- .../Security/CWE/CWE-036/OpenStream.ql | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.ql b/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.ql index d95b9d720033..5835c3f17efa 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.ql @@ -22,13 +22,6 @@ class URLConstructor extends ClassInstanceExpr { } } -class URLOpenStreamCsv extends SinkModelCsv { - override predicate row(string row) { - //"package;type;overrides;name;signature;ext;inputspec;kind", - row = "java.net;URL;true;openStream;();;Argument[-1];url-open-stream" - } -} - class URLOpenStreamMethod extends Method { URLOpenStreamMethod() { this.getDeclaringType() instanceof TypeUrl and @@ -41,7 +34,13 @@ class RemoteURLToOpenStreamFlowConfig extends TaintTracking::Configuration { override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } - override predicate isSink(DataFlow::Node sink) { sinkNode(sink, "url-open-stream") } + override predicate isSink(DataFlow::Node sink) { + exists(MethodAccess m | + sink.asExpr() = m.getQualifier() and m.getMethod() instanceof URLOpenStreamMethod + ) + or + sinkNode(sink, "url-open-stream") + } override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { exists(URLConstructor u |