diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index fa17f4d6742d..acd0cedabcd1 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -28,7 +28,7 @@ jobs: steps: - name: Setup dotnet - uses: actions/setup-dotnet@v2 + uses: actions/setup-dotnet@v3 with: dotnet-version: 6.0.202 diff --git a/java/ql/lib/change-notes/2022-09-22-stringjoiner-summaries.md b/java/ql/lib/change-notes/2022-09-22-stringjoiner-summaries.md new file mode 100644 index 000000000000..d1784d013f61 --- /dev/null +++ b/java/ql/lib/change-notes/2022-09-22-stringjoiner-summaries.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added new flow steps for `java.util.StringJoiner`. diff --git a/java/ql/lib/semmle/code/java/frameworks/Strings.qll b/java/ql/lib/semmle/code/java/frameworks/Strings.qll index c09b959254dd..f913f941df1c 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Strings.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Strings.qll @@ -64,7 +64,15 @@ private class StringSummaryCsv extends SummaryModelCsv { "java.lang;StringBuilder;true;StringBuilder;;;Argument[0];Argument[-1];taint;manual", "java.lang;CharSequence;true;charAt;;;Argument[-1];ReturnValue;taint;manual", "java.lang;CharSequence;true;subSequence;;;Argument[-1];ReturnValue;taint;manual", - "java.lang;CharSequence;true;toString;;;Argument[-1];ReturnValue;taint;manual" + "java.lang;CharSequence;true;toString;;;Argument[-1];ReturnValue;taint;manual", + "java.util;StringJoiner;false;StringJoiner;;;Argument[0..2];Argument[-1];taint;manual", + "java.util;StringJoiner;false;add;;;Argument[0];Argument[-1];taint;manual", + "java.util;StringJoiner;false;add;;;Argument[-1];ReturnValue;value;manual", + "java.util;StringJoiner;false;merge;;;Argument[0];Argument[-1];taint;manual", + "java.util;StringJoiner;false;merge;;;Argument[-1];ReturnValue;value;manual", + "java.util;StringJoiner;false;setEmptyValue;;;Argument[0];Argument[-1];taint;manual", + "java.util;StringJoiner;false;setEmptyValue;;;Argument[-1];ReturnValue;value;manual", + "java.util;StringJoiner;false;toString;;;Argument[-1];ReturnValue;taint;manual", ] } } diff --git a/java/ql/test/library-tests/dataflow/taint/StringJoinerTests.java b/java/ql/test/library-tests/dataflow/taint/StringJoinerTests.java new file mode 100644 index 000000000000..a44fe56ca2e5 --- /dev/null +++ b/java/ql/test/library-tests/dataflow/taint/StringJoinerTests.java @@ -0,0 +1,92 @@ +import java.util.StringJoiner; + +public class StringJoinerTests { + + Object taint() { + return null; + } + + void sink(Object o) {} + + public void test() throws Exception { + { + // "java.util;StringJoiner;false;StringJoiner;(CharSequence);;Argument[0];Argument[-1];taint;manual" + StringJoiner out = null; + CharSequence in = (CharSequence) taint(); + out = new StringJoiner(in); + sink(out); + } + { + // "java.util;StringJoiner;false;StringJoiner;(CharSequence,CharSequence,CharSequence);;Argument[0];Argument[-1];taint;manual" + StringJoiner out = null; + CharSequence in = (CharSequence) taint(); + out = new StringJoiner(in, null, null); + sink(out); + } + { + // "java.util;StringJoiner;false;StringJoiner;(CharSequence,CharSequence,CharSequence);;Argument[1];Argument[-1];taint;manual" + StringJoiner out = null; + CharSequence in = (CharSequence) taint(); + out = new StringJoiner(null, in, null); + sink(out); + } + { + // "java.util;StringJoiner;false;StringJoiner;(CharSequence,CharSequence,CharSequence);;Argument[2];Argument[-1];taint;manual" + StringJoiner out = null; + CharSequence in = (CharSequence) taint(); + out = new StringJoiner(null, null, in); + sink(out); + } + { + // "java.util;StringJoiner;false;add;;;Argument[-1];ReturnValue;value;manual" + StringJoiner out = null; + StringJoiner in = (StringJoiner) taint(); + out = in.add(null); + sink(out); + } + { + // "java.util;StringJoiner;false;add;;;Argument[0];Argument[-1];taint;manual" + StringJoiner out = null; + CharSequence in = (CharSequence) taint(); + out.add(in); + sink(out); + } + { + // "java.util;StringJoiner;false;merge;;;Argument[-1];ReturnValue;value;manual" + StringJoiner out = null; + StringJoiner in = (StringJoiner) taint(); + out = in.merge(null); + sink(out); + } + { + // "java.util;StringJoiner;false;merge;;;Argument[0];Argument[-1];taint;manual" + StringJoiner out = null; + StringJoiner in = (StringJoiner) taint(); + out.merge(in); + sink(out); + } + { + // "java.util;StringJoiner;false;setEmptyValue;;;Argument[-1];ReturnValue;taint;manual" + StringJoiner out = null; + StringJoiner in = (StringJoiner) taint(); + out = in.setEmptyValue(null); + sink(out); + } + { + // "java.util;StringJoiner;false;setEmptyValue;;;Argument[0];Argument[-1];taint;manual" + StringJoiner out = null; + CharSequence in = (CharSequence) taint(); + out.setEmptyValue(in); + sink(out); + } + { + // "java.util;StringJoiner;false;toString;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + StringJoiner in = (StringJoiner) taint(); + out = in.toString(); + sink(out); + } + + } + +} diff --git a/java/ql/test/library-tests/dataflow/taint/test.expected b/java/ql/test/library-tests/dataflow/taint/test.expected index 8b7d85321b4a..555dbb023b78 100644 --- a/java/ql/test/library-tests/dataflow/taint/test.expected +++ b/java/ql/test/library-tests/dataflow/taint/test.expected @@ -72,6 +72,17 @@ | StringBuilderTests.java:70:15:70:21 | taint(...) | StringBuilderTests.java:73:10:73:26 | new String(...) | | StringBuilderTests.java:79:15:79:21 | taint(...) | StringBuilderTests.java:80:10:80:40 | toString(...) | | StringBuilderTests.java:86:15:86:21 | taint(...) | StringBuilderTests.java:87:10:87:27 | substring(...) | +| StringJoinerTests.java:15:37:15:43 | taint(...) | StringJoinerTests.java:17:9:17:11 | out | +| StringJoinerTests.java:22:37:22:43 | taint(...) | StringJoinerTests.java:24:9:24:11 | out | +| StringJoinerTests.java:29:37:29:43 | taint(...) | StringJoinerTests.java:31:9:31:11 | out | +| StringJoinerTests.java:36:37:36:43 | taint(...) | StringJoinerTests.java:38:9:38:11 | out | +| StringJoinerTests.java:43:37:43:43 | taint(...) | StringJoinerTests.java:45:9:45:11 | out | +| StringJoinerTests.java:50:37:50:43 | taint(...) | StringJoinerTests.java:52:9:52:11 | out | +| StringJoinerTests.java:57:37:57:43 | taint(...) | StringJoinerTests.java:59:9:59:11 | out | +| StringJoinerTests.java:64:37:64:43 | taint(...) | StringJoinerTests.java:66:9:66:11 | out | +| StringJoinerTests.java:71:37:71:43 | taint(...) | StringJoinerTests.java:73:9:73:11 | out | +| StringJoinerTests.java:78:37:78:43 | taint(...) | StringJoinerTests.java:80:9:80:11 | out | +| StringJoinerTests.java:85:37:85:43 | taint(...) | StringJoinerTests.java:87:9:87:11 | out | | Varargs.java:7:8:7:14 | taint(...) | Varargs.java:14:10:14:10 | s | | Varargs.java:8:8:8:14 | taint(...) | Varargs.java:19:10:19:10 | s | | Varargs.java:8:17:8:23 | taint(...) | Varargs.java:19:10:19:10 | s |