From 105984f7de7e13b49d8875b0fba6608ec80e3929 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 6 May 2024 10:01:34 +0200 Subject: [PATCH 1/9] Java: Make param module for MaD inline test. --- .../CaptureTypeBasedSummaryModels.ql | 52 +++++++++++++------ 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/java/ql/test/utils/modelgenerator/typebasedflow/CaptureTypeBasedSummaryModels.ql b/java/ql/test/utils/modelgenerator/typebasedflow/CaptureTypeBasedSummaryModels.ql index fe77abaa6df..88932d3a1ef 100644 --- a/java/ql/test/utils/modelgenerator/typebasedflow/CaptureTypeBasedSummaryModels.ql +++ b/java/ql/test/utils/modelgenerator/typebasedflow/CaptureTypeBasedSummaryModels.ql @@ -1,26 +1,44 @@ import java import utils.modelgenerator.internal.CaptureTypeBasedSummaryModels -private string expects() { - exists(Javadoc doc | - doc.getChild(0).toString().regexpCapture(" *(SPURIOUS-)?MaD=(.*)", 2) = result - ) +signature module InlineMadTestConfigSig { + /** + * Gets a relevant code comment, if any. + */ + string getComment(); + + /** + * Gets an identified summary, if any. + */ + string getCapturedSummary(); } -private string flows() { result = captureFlow(_) } +module InlineMadTest { + private string expects() { + Input::getComment().regexpCapture(" *(SPURIOUS-)?MaD=(.*)", 2) = result + } -query predicate unexpectedSummary(string msg) { - exists(string flow | - flow = flows() and - not flow = expects() and - msg = "Unexpected summary found: " + flow - ) + query predicate unexpectedSummary(string msg) { + exists(string flow | + flow = Input::getCapturedSummary() and + not flow = expects() and + msg = "Unexpected summary found: " + flow + ) + } + + query predicate expectedSummary(string msg) { + exists(string e | + e = expects() and + not e = Input::getCapturedSummary() and + msg = "Expected summary missing: " + e + ) + } } -query predicate expectedSummary(string msg) { - exists(string e | - e = expects() and - not e = flows() and - msg = "Expected summary missing: " + e - ) +module InlineMadTestConfig implements InlineMadTestConfigSig { + string getComment() { result = any(Javadoc doc).getChild(0).toString() } + + string getCapturedSummary() { result = captureFlow(_) } } + +import InlineMadTest From 6815bcaa80027a01665d5783821d4fe4fb3fea85 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 6 May 2024 10:19:39 +0200 Subject: [PATCH 2/9] Java: Move param module into TestUtilities. --- java/ql/test/TestUtilities/InlineMadTest.qll | 33 +++++++++++++++++ .../CaptureTypeBasedSummaryModels.ql | 35 +------------------ 2 files changed, 34 insertions(+), 34 deletions(-) create mode 100644 java/ql/test/TestUtilities/InlineMadTest.qll diff --git a/java/ql/test/TestUtilities/InlineMadTest.qll b/java/ql/test/TestUtilities/InlineMadTest.qll new file mode 100644 index 00000000000..64badab0dca --- /dev/null +++ b/java/ql/test/TestUtilities/InlineMadTest.qll @@ -0,0 +1,33 @@ +signature module InlineMadTestConfigSig { + /** + * Gets a relevant code comment, if any. + */ + string getComment(); + + /** + * Gets an identified summary, if any. + */ + string getCapturedSummary(); +} + +module InlineMadTest { + private string expects() { + Input::getComment().regexpCapture(" *(SPURIOUS-)?MaD=(.*)", 2) = result + } + + query predicate unexpectedSummary(string msg) { + exists(string flow | + flow = Input::getCapturedSummary() and + not flow = expects() and + msg = "Unexpected summary found: " + flow + ) + } + + query predicate expectedSummary(string msg) { + exists(string e | + e = expects() and + not e = Input::getCapturedSummary() and + msg = "Expected summary missing: " + e + ) + } +} diff --git a/java/ql/test/utils/modelgenerator/typebasedflow/CaptureTypeBasedSummaryModels.ql b/java/ql/test/utils/modelgenerator/typebasedflow/CaptureTypeBasedSummaryModels.ql index 88932d3a1ef..c5c509ac326 100644 --- a/java/ql/test/utils/modelgenerator/typebasedflow/CaptureTypeBasedSummaryModels.ql +++ b/java/ql/test/utils/modelgenerator/typebasedflow/CaptureTypeBasedSummaryModels.ql @@ -1,40 +1,7 @@ import java +import TestUtilities.InlineMadTest import utils.modelgenerator.internal.CaptureTypeBasedSummaryModels -signature module InlineMadTestConfigSig { - /** - * Gets a relevant code comment, if any. - */ - string getComment(); - - /** - * Gets an identified summary, if any. - */ - string getCapturedSummary(); -} - -module InlineMadTest { - private string expects() { - Input::getComment().regexpCapture(" *(SPURIOUS-)?MaD=(.*)", 2) = result - } - - query predicate unexpectedSummary(string msg) { - exists(string flow | - flow = Input::getCapturedSummary() and - not flow = expects() and - msg = "Unexpected summary found: " + flow - ) - } - - query predicate expectedSummary(string msg) { - exists(string e | - e = expects() and - not e = Input::getCapturedSummary() and - msg = "Expected summary missing: " + e - ) - } -} - module InlineMadTestConfig implements InlineMadTestConfigSig { string getComment() { result = any(Javadoc doc).getChild(0).toString() } From 7cb8a6c52f9219abd305b3e2a7d6e4f3c29f3eac Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 6 May 2024 11:01:23 +0200 Subject: [PATCH 3/9] Java: Inline models as data expected output as comments in the java files and add a test. --- .../dataflow/CaptureModels.expected | 2 + .../modelgenerator/dataflow/CaptureModels.ql | 11 + .../modelgenerator/dataflow/p/Factory.java | 42 ++-- .../modelgenerator/dataflow/p/FinalClass.java | 18 +- .../modelgenerator/dataflow/p/FluentAPI.java | 18 +- .../dataflow/p/ImmutablePojo.java | 37 ++-- .../dataflow/p/InnerClasses.java | 29 +-- .../dataflow/p/InnerHolder.java | 57 ++--- .../modelgenerator/dataflow/p/Joiner.java | 203 +++++++++--------- .../dataflow/p/MultipleImpl2.java | 29 +-- .../dataflow/p/MultipleImpls.java | 59 ++--- .../modelgenerator/dataflow/p/ParamFlow.java | 97 +++++---- .../utils/modelgenerator/dataflow/p/Pojo.java | 148 +++++++------ .../p/PrivateFlowViaPublicInterface.java | 82 +++---- 14 files changed, 439 insertions(+), 393 deletions(-) create mode 100644 java/ql/test/utils/modelgenerator/dataflow/CaptureModels.expected create mode 100644 java/ql/test/utils/modelgenerator/dataflow/CaptureModels.ql diff --git a/java/ql/test/utils/modelgenerator/dataflow/CaptureModels.expected b/java/ql/test/utils/modelgenerator/dataflow/CaptureModels.expected new file mode 100644 index 00000000000..ee55a9c6ba6 --- /dev/null +++ b/java/ql/test/utils/modelgenerator/dataflow/CaptureModels.expected @@ -0,0 +1,2 @@ +unexpectedSummary +expectedSummary diff --git a/java/ql/test/utils/modelgenerator/dataflow/CaptureModels.ql b/java/ql/test/utils/modelgenerator/dataflow/CaptureModels.ql new file mode 100644 index 00000000000..1a2dbd03d7a --- /dev/null +++ b/java/ql/test/utils/modelgenerator/dataflow/CaptureModels.ql @@ -0,0 +1,11 @@ +import java +import utils.modelgenerator.internal.CaptureSummaryFlowQuery +import TestUtilities.InlineMadTest + +module InlineMadTestConfig implements InlineMadTestConfigSig { + string getComment() { result = any(Javadoc doc).getChild(0).toString() } + + string getCapturedSummary() { result = captureFlow(_) } +} + +import InlineMadTest diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/Factory.java b/java/ql/test/utils/modelgenerator/dataflow/p/Factory.java index a6e7ce5fff6..84b55a812c9 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/Factory.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/Factory.java @@ -2,29 +2,31 @@ package p; public final class Factory { - private String value; + private String value; - private int intValue; + private int intValue; - public static Factory create(String value, int foo) { - return new Factory(value, foo); - } + // MaD=p;Factory;false;create;(String,int);;Argument[0];ReturnValue;taint;df-generated + public static Factory create(String value, int foo) { + return new Factory(value, foo); + } - public static Factory create(String value) { - return new Factory(value, 0); - } + // MaD=p;Factory;false;create;(String);;Argument[0];ReturnValue;taint;df-generated + public static Factory create(String value) { + return new Factory(value, 0); + } - private Factory(String value, int intValue) { - this.value = value; - this.intValue = intValue; - } + private Factory(String value, int intValue) { + this.value = value; + this.intValue = intValue; + } - public String getValue() { - return value; - } + // MaD=p;Factory;false;getValue;();;Argument[this];ReturnValue;taint;df-generated + public String getValue() { + return value; + } - public int getIntValue() { - return intValue; - } - -} \ No newline at end of file + public int getIntValue() { + return intValue; + } +} diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/FinalClass.java b/java/ql/test/utils/modelgenerator/dataflow/p/FinalClass.java index 224fc44a0bc..5073f435233 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/FinalClass.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/FinalClass.java @@ -2,14 +2,14 @@ package p; public final class FinalClass { - private static final String C = "constant"; + private static final String C = "constant"; - public String returnsInput(String input) { - return input; - } + // MaD=p;FinalClass;false;returnsInput;(String);;Argument[0];ReturnValue;taint;df-generated + public String returnsInput(String input) { + return input; + } - public String returnsConstant() { - return C; - } - -} \ No newline at end of file + public String returnsConstant() { + return C; + } +} diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/FluentAPI.java b/java/ql/test/utils/modelgenerator/dataflow/p/FluentAPI.java index 65887625d27..2bb2bb97604 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/FluentAPI.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/FluentAPI.java @@ -2,14 +2,14 @@ package p; public final class FluentAPI { - public FluentAPI returnsThis(String input) { - return this; - } + // MaD=p;FluentAPI;false;returnsThis;(String);;Argument[this];ReturnValue;value;df-generated + public FluentAPI returnsThis(String input) { + return this; + } - public class Inner { - public FluentAPI notThis(String input) { - return FluentAPI.this; - } + public class Inner { + public FluentAPI notThis(String input) { + return FluentAPI.this; } - -} \ No newline at end of file + } +} diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/ImmutablePojo.java b/java/ql/test/utils/modelgenerator/dataflow/p/ImmutablePojo.java index 660c1970bd3..38a9b472f62 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/ImmutablePojo.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/ImmutablePojo.java @@ -2,25 +2,28 @@ package p; public final class ImmutablePojo { - private final String value; + private final String value; - private final long x; + private final long x; - public ImmutablePojo(String value, int x) { - this.value = value; - this.x = x; - } + // MaD=p;ImmutablePojo;false;ImmutablePojo;(String,int);;Argument[0];Argument[this];taint;df-generated + public ImmutablePojo(String value, int x) { + this.value = value; + this.x = x; + } - public String getValue() { - return value; - } + // MaD=p;ImmutablePojo;false;getValue;();;Argument[this];ReturnValue;taint;df-generated + public String getValue() { + return value; + } - public long getX() { - return x; - } + public long getX() { + return x; + } - public String or(String defaultValue) { - return value != null ? value : defaultValue; - } - -} \ No newline at end of file + // MaD=p;ImmutablePojo;false;or;(String);;Argument[0];ReturnValue;taint;df-generated + // MaD=p;ImmutablePojo;false;or;(String);;Argument[this];ReturnValue;taint;df-generated + public String or(String defaultValue) { + return value != null ? value : defaultValue; + } +} diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/InnerClasses.java b/java/ql/test/utils/modelgenerator/dataflow/p/InnerClasses.java index 936166eddf3..54f014fec93 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/InnerClasses.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/InnerClasses.java @@ -1,21 +1,22 @@ package p; public class InnerClasses { - - class IgnoreMe { - public String no(String input) { - return input; - } - } - - public class CaptureMe { - public String yesCm(String input) { - return input; - } - } - public String yes(String input) { - return input; + class IgnoreMe { + public String no(String input) { + return input; } + } + public class CaptureMe { + // MaD=p;InnerClasses$CaptureMe;true;yesCm;(String);;Argument[0];ReturnValue;taint;df-generated + public String yesCm(String input) { + return input; + } + } + + // MaD=p;InnerClasses;true;yes;(String);;Argument[0];ReturnValue;taint;df-generated + public String yes(String input) { + return input; + } } diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/InnerHolder.java b/java/ql/test/utils/modelgenerator/dataflow/p/InnerHolder.java index 5dc07cadd51..ef872942191 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/InnerHolder.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/InnerHolder.java @@ -2,36 +2,39 @@ package p; public final class InnerHolder { - private class Context { - private String value; + private class Context { + private String value; - Context(String value) { - this.value = value; - } - - public String getValue() { - return value; - } - } - - private Context context = null; - - private StringBuilder sb = new StringBuilder(); - - public void setContext(String value) { - context = new Context(value); - } - - public void explicitSetContext(String value) { - this.context = new Context(value); - } - - public void append(String value) { - sb.append(value); + Context(String value) { + this.value = value; } public String getValue() { - return context.getValue(); + return value; } + } -} \ No newline at end of file + private Context context = null; + + private StringBuilder sb = new StringBuilder(); + + // MaD=p;InnerHolder;false;setContext;(String);;Argument[0];Argument[this];taint;df-generated + public void setContext(String value) { + context = new Context(value); + } + + // MaD=p;InnerHolder;false;explicitSetContext;(String);;Argument[0];Argument[this];taint;df-generated + public void explicitSetContext(String value) { + this.context = new Context(value); + } + + // MaD=p;InnerHolder;false;append;(String);;Argument[0];Argument[this];taint;df-generated + public void append(String value) { + sb.append(value); + } + + // MaD=p;InnerHolder;false;getValue;();;Argument[this];ReturnValue;taint;df-generated + public String getValue() { + return context.getValue(); + } +} diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/Joiner.java b/java/ql/test/utils/modelgenerator/dataflow/p/Joiner.java index d9869815bc5..daa939ebe51 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/Joiner.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/Joiner.java @@ -4,115 +4,122 @@ import java.util.Arrays; import java.util.Objects; public final class Joiner { - private final String prefix; - private final String delimiter; - private final String suffix; - private String[] elts; - private int size; - private int len; - private String emptyValue; - public Joiner(CharSequence delimiter) { - this(delimiter, "", ""); - } + private final String prefix; + private final String delimiter; + private final String suffix; + private String[] elts; + private int size; + private int len; + private String emptyValue; - public Joiner(CharSequence delimiter, - CharSequence prefix, - CharSequence suffix) { - Objects.requireNonNull(prefix, "The prefix must not be null"); - Objects.requireNonNull(delimiter, "The delimiter must not be null"); - Objects.requireNonNull(suffix, "The suffix must not be null"); - this.prefix = prefix.toString(); - this.delimiter = delimiter.toString(); - this.suffix = suffix.toString(); - checkAddLength(0, 0); - } + // MaD=p;Joiner;false;Joiner;(CharSequence);;Argument[0];Argument[this];taint;df-generated + public Joiner(CharSequence delimiter) { + this(delimiter, "", ""); + } - public Joiner setEmptyValue(CharSequence emptyValue) { - this.emptyValue = Objects.requireNonNull(emptyValue, - "The empty value must not be null").toString(); - return this; - } + // MaD=p;Joiner;false;Joiner;(CharSequence,CharSequence,CharSequence);;Argument[0];Argument[this];taint;df-generated + // MaD=p;Joiner;false;Joiner;(CharSequence,CharSequence,CharSequence);;Argument[1];Argument[this];taint;df-generated + // MaD=p;Joiner;false;Joiner;(CharSequence,CharSequence,CharSequence);;Argument[2];Argument[this];taint;df-generated + public Joiner(CharSequence delimiter, CharSequence prefix, CharSequence suffix) { + Objects.requireNonNull(prefix, "The prefix must not be null"); + Objects.requireNonNull(delimiter, "The delimiter must not be null"); + Objects.requireNonNull(suffix, "The suffix must not be null"); + this.prefix = prefix.toString(); + this.delimiter = delimiter.toString(); + this.suffix = suffix.toString(); + checkAddLength(0, 0); + } - private static int getChars(String s, char[] chars, int start) { - int len = s.length(); - s.getChars(0, len, chars, start); - return len; - } + // MaD=p;Joiner;false;setEmptyValue;(CharSequence);;Argument[0];Argument[this];taint;df-generated + // MaD=p;Joiner;false;setEmptyValue;(CharSequence);;Argument[this];ReturnValue;value;df-generated + public Joiner setEmptyValue(CharSequence emptyValue) { + this.emptyValue = + Objects.requireNonNull(emptyValue, "The empty value must not be null").toString(); + return this; + } - @Override - public String toString() { - final String[] elts = this.elts; - if (elts == null && emptyValue != null) { - return emptyValue; - } - final int size = this.size; - final int addLen = prefix.length() + suffix.length(); - if (addLen == 0) { - compactElts(); - return size == 0 ? "" : elts[0]; - } - final String delimiter = this.delimiter; - final char[] chars = new char[len + addLen]; - int k = getChars(prefix, chars, 0); - if (size > 0) { - k += getChars(elts[0], chars, k); - for (int i = 1; i < size; i++) { - k += getChars(delimiter, chars, k); - k += getChars(elts[i], chars, k); - } - } - k += getChars(suffix, chars, k); - return new String(chars); - } + private static int getChars(String s, char[] chars, int start) { + int len = s.length(); + s.getChars(0, len, chars, start); + return len; + } - public Joiner add(CharSequence newElement) { - final String elt = String.valueOf(newElement); - if (elts == null) { - elts = new String[8]; - } else { - if (size == elts.length) - elts = Arrays.copyOf(elts, 2 * size); - len = checkAddLength(len, delimiter.length()); - } - len = checkAddLength(len, elt.length()); - elts[size++] = elt; - return this; + @Override + public String toString() { + final String[] elts = this.elts; + if (elts == null && emptyValue != null) { + return emptyValue; } + final int size = this.size; + final int addLen = prefix.length() + suffix.length(); + if (addLen == 0) { + compactElts(); + return size == 0 ? "" : elts[0]; + } + final String delimiter = this.delimiter; + final char[] chars = new char[len + addLen]; + int k = getChars(prefix, chars, 0); + if (size > 0) { + k += getChars(elts[0], chars, k); + for (int i = 1; i < size; i++) { + k += getChars(delimiter, chars, k); + k += getChars(elts[i], chars, k); + } + } + k += getChars(suffix, chars, k); + return new String(chars); + } - private int checkAddLength(int oldLen, int inc) { - long newLen = (long)oldLen + (long)inc; - long tmpLen = newLen + (long)prefix.length() + (long)suffix.length(); - if (tmpLen != (int)tmpLen) { - throw new OutOfMemoryError("Requested array size exceeds VM limit"); - } - return (int)newLen; + // MaD=p;Joiner;false;add;(CharSequence);;Argument[this];ReturnValue;value;df-generated + public Joiner add(CharSequence newElement) { + final String elt = String.valueOf(newElement); + if (elts == null) { + elts = new String[8]; + } else { + if (size == elts.length) elts = Arrays.copyOf(elts, 2 * size); + len = checkAddLength(len, delimiter.length()); } + len = checkAddLength(len, elt.length()); + elts[size++] = elt; + return this; + } - public Joiner merge(Joiner other) { - Objects.requireNonNull(other); - if (other.elts == null) { - return this; - } - other.compactElts(); - return add(other.elts[0]); + private int checkAddLength(int oldLen, int inc) { + long newLen = (long) oldLen + (long) inc; + long tmpLen = newLen + (long) prefix.length() + (long) suffix.length(); + if (tmpLen != (int) tmpLen) { + throw new OutOfMemoryError("Requested array size exceeds VM limit"); } + return (int) newLen; + } - private void compactElts() { - if (size > 1) { - final char[] chars = new char[len]; - int i = 1, k = getChars(elts[0], chars, 0); - do { - k += getChars(delimiter, chars, k); - k += getChars(elts[i], chars, k); - elts[i] = null; - } while (++i < size); - size = 1; - elts[0] = new String(chars); - } + // MaD=p;Joiner;false;merge;(Joiner);;Argument[this];ReturnValue;value;df-generated + public Joiner merge(Joiner other) { + Objects.requireNonNull(other); + if (other.elts == null) { + return this; } + other.compactElts(); + return add(other.elts[0]); + } - public int length() { - return (size == 0 && emptyValue != null) ? emptyValue.length() : - len + prefix.length() + suffix.length(); + private void compactElts() { + if (size > 1) { + final char[] chars = new char[len]; + int i = 1, k = getChars(elts[0], chars, 0); + do { + k += getChars(delimiter, chars, k); + k += getChars(elts[i], chars, k); + elts[i] = null; + } while (++i < size); + size = 1; + elts[0] = new String(chars); } -} \ No newline at end of file + } + + public int length() { + return (size == 0 && emptyValue != null) + ? emptyValue.length() + : len + prefix.length() + suffix.length(); + } +} diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/MultipleImpl2.java b/java/ql/test/utils/modelgenerator/dataflow/p/MultipleImpl2.java index 9de2d59b2e4..7c2e2ed9211 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/MultipleImpl2.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/MultipleImpl2.java @@ -2,22 +2,23 @@ package p; class MultipleImpl2 { - // Multiple implementations of the same interface. - // This is used to test that we only generate a summary model and - // not neutral summary model for `IInterface.m`. - public interface IInterface { - Object m(Object value); - } + // Multiple implementations of the same interface. + // This is used to test that we only generate a summary model and + // not neutral summary model for `IInterface.m`. + public interface IInterface { + // MaD=p;MultipleImpl2$IInterface;true;m;(Object);;Argument[0];ReturnValue;taint;df-generated + Object m(Object value); + } - public class Impl1 implements IInterface { - public Object m(Object value) { - return null; - } + public class Impl1 implements IInterface { + public Object m(Object value) { + return null; } + } - public class Impl2 implements IInterface { - public Object m(Object value) { - return value; - } + public class Impl2 implements IInterface { + public Object m(Object value) { + return value; } + } } diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/MultipleImpls.java b/java/ql/test/utils/modelgenerator/dataflow/p/MultipleImpls.java index a6697393dbc..8cdde304bd5 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/MultipleImpls.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/MultipleImpls.java @@ -4,35 +4,38 @@ import java.util.concurrent.Callable; public class MultipleImpls { - public static interface Strategy { - String doSomething(String value); + public static interface Strategy { + // MaD=p;MultipleImpls$Strategy;true;doSomething;(String);;Argument[0];Argument[this];taint;df-generated + // MaD=p;MultipleImpls$Strategy;true;doSomething;(String);;Argument[0];ReturnValue;taint;df-generated + String doSomething(String value); + } + + public static class Strat1 implements Strategy { + public String doSomething(String value) { + return value; + } + } + + // implements in different library should not count as impl + public static class Strat3 implements Callable { + + @Override + public String call() throws Exception { + return null; + } + } + + public static class Strat2 implements Strategy { + private String foo; + + public String doSomething(String value) { + this.foo = value; + return "none"; } - public static class Strat1 implements Strategy { - public String doSomething(String value) { - return value; - } - } - - // implements in different library should not count as impl - public static class Strat3 implements Callable { - - @Override - public String call() throws Exception { - return null; - } - - } - public static class Strat2 implements Strategy { - private String foo; - - public String doSomething(String value) { - this.foo = value; - return "none"; - } - - public String getValue() { - return this.foo; - } + // MaD=p;MultipleImpls$Strat2;true;getValue;();;Argument[this];ReturnValue;taint;df-generated + public String getValue() { + return this.foo; } + } } diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/ParamFlow.java b/java/ql/test/utils/modelgenerator/dataflow/p/ParamFlow.java index 8b58c377316..7d9dac157c2 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/ParamFlow.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/ParamFlow.java @@ -1,64 +1,71 @@ package p; -import java.util.Iterator; -import java.util.List; import java.io.IOException; import java.io.OutputStream; - +import java.util.Iterator; +import java.util.List; public class ParamFlow { - public String returnsInput(String input) { - return input; - } + // MaD=p;ParamFlow;true;returnsInput;(String);;Argument[0];ReturnValue;taint;df-generated + public String returnsInput(String input) { + return input; + } - public int ignorePrimitiveReturnValue(String input) { - return input.length(); - } + public int ignorePrimitiveReturnValue(String input) { + return input.length(); + } - public String returnMultipleParameters(String one, String two) { - if (System.currentTimeMillis() > 100) { - return two; - } - return one; + // MaD=p;ParamFlow;true;returnMultipleParameters;(String,String);;Argument[0];ReturnValue;taint;df-generated + // MaD=p;ParamFlow;true;returnMultipleParameters;(String,String);;Argument[1];ReturnValue;taint;df-generated + public String returnMultipleParameters(String one, String two) { + if (System.currentTimeMillis() > 100) { + return two; } + return one; + } - public String returnArrayElement(String[] input) { - return input[0]; - } + // MaD=p;ParamFlow;true;returnArrayElement;(String[]);;Argument[0].ArrayElement;ReturnValue;taint;df-generated + public String returnArrayElement(String[] input) { + return input[0]; + } - public String returnVarArgElement(String... input) { - return input[0]; - } + // MaD=p;ParamFlow;true;returnVarArgElement;(String[]);;Argument[0].ArrayElement;ReturnValue;taint;df-generated + public String returnVarArgElement(String... input) { + return input[0]; + } - public String returnCollectionElement(List input) { - return input.get(0); - } + // MaD=p;ParamFlow;true;returnCollectionElement;(List);;Argument[0].Element;ReturnValue;taint;df-generated + public String returnCollectionElement(List input) { + return input.get(0); + } - public String returnIteratorElement(Iterator input) { - return input.next(); - } + // MaD=p;ParamFlow;true;returnIteratorElement;(Iterator);;Argument[0].Element;ReturnValue;taint;df-generated + public String returnIteratorElement(Iterator input) { + return input.next(); + } - public String returnIterableElement(Iterable input) { - return input.iterator().next(); - } + // MaD=p;ParamFlow;true;returnIterableElement;(Iterable);;Argument[0].Element;ReturnValue;taint;df-generated + public String returnIterableElement(Iterable input) { + return input.iterator().next(); + } - public Class mapType(Class input) { - return input; - } + public Class mapType(Class input) { + return input; + } - public void writeChunked(byte[] data, OutputStream output) - throws IOException { - output.write(data, 0, data.length); - } - - public void writeChunked(char[] data, OutputStream output) - throws IOException { - output.write(String.valueOf(data).getBytes(), 0, data.length); - } + // MaD=p;ParamFlow;true;writeChunked;(byte[],OutputStream);;Argument[0];Argument[1];taint;df-generated + public void writeChunked(byte[] data, OutputStream output) throws IOException { + output.write(data, 0, data.length); + } - public void addTo(String data, List target) { - target.add(data); - } + // MaD=p;ParamFlow;true;writeChunked;(char[],OutputStream);;Argument[0];Argument[1];taint;df-generated + public void writeChunked(char[] data, OutputStream output) throws IOException { + output.write(String.valueOf(data).getBytes(), 0, data.length); + } -} \ No newline at end of file + // MaD=p;ParamFlow;true;addTo;(String,List);;Argument[0];Argument[1].Element;taint;df-generated + public void addTo(String data, List target) { + target.add(data); + } +} diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/Pojo.java b/java/ql/test/utils/modelgenerator/dataflow/p/Pojo.java index 40dfa56ae86..15fbda5bc79 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/Pojo.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/Pojo.java @@ -8,91 +8,97 @@ import java.util.List; public final class Pojo { - private class Holder { - private String value; - - Holder(String value) { - this.value = value; - } - - int length() { - return value.length(); - } - } - + private class Holder { private String value; - private int intValue = 2; - - private byte[] byteArray = new byte[] {1, 2, 3} ; - private float[] floatArray = new float[] {1, 2, 3} ; - private char[] charArray = new char[] {'a', 'b', 'c'} ; - private List charList = Arrays.asList('a', 'b', 'c'); - private Byte[] byteObjectArray = new Byte[] { 1, 2, 3 }; - - public String getValue() { - return value; + Holder(String value) { + this.value = value; } - public void setValue(String value) { - this.value = value; + int length() { + return value.length(); } + } - public int doNotSetValue(String value) { - Holder h = new Holder(value); - return h.length(); - } + private String value; - public int getIntValue() { - return intValue; - } + private int intValue = 2; - public Integer getBoxedValue() { - return Integer.valueOf(intValue); - } + private byte[] byteArray = new byte[] {1, 2, 3}; + private float[] floatArray = new float[] {1, 2, 3}; + private char[] charArray = new char[] {'a', 'b', 'c'}; + private List charList = Arrays.asList('a', 'b', 'c'); + private Byte[] byteObjectArray = new Byte[] {1, 2, 3}; - public int[] getPrimitiveArray() { - return new int[] { intValue }; - } + // MaD=p;Pojo;false;getValue;();;Argument[this];ReturnValue;taint;df-generated + public String getValue() { + return value; + } - public char[] getCharArray() { - return charArray; - } + // MaD=p;Pojo;false;setValue;(String);;Argument[0];Argument[this];taint;df-generated + public void setValue(String value) { + this.value = value; + } - public byte[] getByteArray() { - return byteArray; - } - - public float[] getFloatArray() { - return floatArray; - } + public int doNotSetValue(String value) { + Holder h = new Holder(value); + return h.length(); + } - public Integer[] getBoxedArray() { - return new Integer[] { Integer.valueOf(intValue) }; - } - - public Collection getBoxedCollection() { - return List.of(Integer.valueOf(intValue)); - } + public int getIntValue() { + return intValue; + } - public List getBoxedChars() { - return charList; - } + public Integer getBoxedValue() { + return Integer.valueOf(intValue); + } - public Byte[] getBoxedBytes() { - return byteObjectArray; - } - - public BigInteger getBigInt() { - return BigInteger.valueOf(intValue); - } + public int[] getPrimitiveArray() { + return new int[] {intValue}; + } - public BigDecimal getBigDecimal() { - return new BigDecimal(value); - } + // MaD=p;Pojo;false;getCharArray;();;Argument[this];ReturnValue;taint;df-generated + public char[] getCharArray() { + return charArray; + } - public void fillIn(List target) { - target.add(value); - } + // MaD=p;Pojo;false;getByteArray;();;Argument[this];ReturnValue;taint;df-generated + public byte[] getByteArray() { + return byteArray; + } -} \ No newline at end of file + public float[] getFloatArray() { + return floatArray; + } + + public Integer[] getBoxedArray() { + return new Integer[] {Integer.valueOf(intValue)}; + } + + public Collection getBoxedCollection() { + return List.of(Integer.valueOf(intValue)); + } + + // MaD=p;Pojo;false;getBoxedChars;();;Argument[this];ReturnValue;taint;df-generated + public List getBoxedChars() { + return charList; + } + + // MaD=p;Pojo;false;getBoxedBytes;();;Argument[this];ReturnValue;taint;df-generated + public Byte[] getBoxedBytes() { + return byteObjectArray; + } + + public BigInteger getBigInt() { + return BigInteger.valueOf(intValue); + } + + public BigDecimal getBigDecimal() { + return new BigDecimal(value); + } + + // MaD=p;Pojo;false;fillIn;(List);;Argument[this];Argument[0].Element;taint;df-generated + public void fillIn(List target) { + target.add(value); + } +} diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/PrivateFlowViaPublicInterface.java b/java/ql/test/utils/modelgenerator/dataflow/p/PrivateFlowViaPublicInterface.java index 59247bfe471..13a2897f08a 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/PrivateFlowViaPublicInterface.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/PrivateFlowViaPublicInterface.java @@ -7,55 +7,55 @@ import java.io.OutputStream; public class PrivateFlowViaPublicInterface { - static class RandomPojo { - public File someFile = new File("someFile"); - } - public static interface SPI { - OutputStream openStream() throws IOException; + static class RandomPojo { + public File someFile = new File("someFile"); + } - default OutputStream openStreamNone() throws IOException { - return null; - }; + public static interface SPI { + // MaD=p;PrivateFlowViaPublicInterface$SPI;true;openStream;();;Argument[this];ReturnValue;taint;df-generated + OutputStream openStream() throws IOException; + + default OutputStream openStreamNone() throws IOException { + return null; + } + ; + } + + private static final class PrivateImplWithSink implements SPI { + + private File file; + + public PrivateImplWithSink(File file) { + this.file = file; } - private static final class PrivateImplWithSink implements SPI { - - private File file; - - public PrivateImplWithSink(File file) { - this.file = file; - } - - @Override - public OutputStream openStream() throws IOException { - return new FileOutputStream(file); - } - + @Override + public OutputStream openStream() throws IOException { + return new FileOutputStream(file); } - - private static final class PrivateImplWithRandomField implements SPI { + } - public PrivateImplWithRandomField(File file) { - } + private static final class PrivateImplWithRandomField implements SPI { - @Override - public OutputStream openStream() throws IOException { - return null; - } - - @Override - public OutputStream openStreamNone() throws IOException { - return new FileOutputStream(new RandomPojo().someFile); - } + public PrivateImplWithRandomField(File file) {} + @Override + public OutputStream openStream() throws IOException { + return null; } - public static SPI createAnSPI(File file) { - return new PrivateImplWithSink(file); - } - - public static SPI createAnSPIWithoutTrackingFile(File file) { - return new PrivateImplWithRandomField(file); + @Override + public OutputStream openStreamNone() throws IOException { + return new FileOutputStream(new RandomPojo().someFile); } + } -} \ No newline at end of file + // MaD=p;PrivateFlowViaPublicInterface;true;createAnSPI;(File);;Argument[0];ReturnValue;taint;df-generated + public static SPI createAnSPI(File file) { + return new PrivateImplWithSink(file); + } + + public static SPI createAnSPIWithoutTrackingFile(File file) { + return new PrivateImplWithRandomField(file); + } +} From a33393d452d8ec5758deb979ae75fbee2eefe74e Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 6 May 2024 11:02:04 +0200 Subject: [PATCH 4/9] Java: Delete old summary models expected output. --- .../dataflow/CaptureSummaryModels.expected | 47 ------------------- .../dataflow/CaptureSummaryModels.qlref | 1 - 2 files changed, 48 deletions(-) delete mode 100644 java/ql/test/utils/modelgenerator/dataflow/CaptureSummaryModels.expected delete mode 100644 java/ql/test/utils/modelgenerator/dataflow/CaptureSummaryModels.qlref diff --git a/java/ql/test/utils/modelgenerator/dataflow/CaptureSummaryModels.expected b/java/ql/test/utils/modelgenerator/dataflow/CaptureSummaryModels.expected deleted file mode 100644 index 50536e850d9..00000000000 --- a/java/ql/test/utils/modelgenerator/dataflow/CaptureSummaryModels.expected +++ /dev/null @@ -1,47 +0,0 @@ -| p;Factory;false;create;(String);;Argument[0];ReturnValue;taint;df-generated | -| p;Factory;false;create;(String,int);;Argument[0];ReturnValue;taint;df-generated | -| p;Factory;false;getValue;();;Argument[this];ReturnValue;taint;df-generated | -| p;FinalClass;false;returnsInput;(String);;Argument[0];ReturnValue;taint;df-generated | -| p;FluentAPI;false;returnsThis;(String);;Argument[this];ReturnValue;value;df-generated | -| p;ImmutablePojo;false;ImmutablePojo;(String,int);;Argument[0];Argument[this];taint;df-generated | -| p;ImmutablePojo;false;getValue;();;Argument[this];ReturnValue;taint;df-generated | -| p;ImmutablePojo;false;or;(String);;Argument[0];ReturnValue;taint;df-generated | -| p;ImmutablePojo;false;or;(String);;Argument[this];ReturnValue;taint;df-generated | -| p;InnerClasses$CaptureMe;true;yesCm;(String);;Argument[0];ReturnValue;taint;df-generated | -| p;InnerClasses;true;yes;(String);;Argument[0];ReturnValue;taint;df-generated | -| p;InnerHolder;false;append;(String);;Argument[0];Argument[this];taint;df-generated | -| p;InnerHolder;false;explicitSetContext;(String);;Argument[0];Argument[this];taint;df-generated | -| p;InnerHolder;false;getValue;();;Argument[this];ReturnValue;taint;df-generated | -| p;InnerHolder;false;setContext;(String);;Argument[0];Argument[this];taint;df-generated | -| p;Joiner;false;Joiner;(CharSequence);;Argument[0];Argument[this];taint;df-generated | -| p;Joiner;false;Joiner;(CharSequence,CharSequence,CharSequence);;Argument[0];Argument[this];taint;df-generated | -| p;Joiner;false;Joiner;(CharSequence,CharSequence,CharSequence);;Argument[1];Argument[this];taint;df-generated | -| p;Joiner;false;Joiner;(CharSequence,CharSequence,CharSequence);;Argument[2];Argument[this];taint;df-generated | -| p;Joiner;false;add;(CharSequence);;Argument[this];ReturnValue;value;df-generated | -| p;Joiner;false;merge;(Joiner);;Argument[this];ReturnValue;value;df-generated | -| p;Joiner;false;setEmptyValue;(CharSequence);;Argument[0];Argument[this];taint;df-generated | -| p;Joiner;false;setEmptyValue;(CharSequence);;Argument[this];ReturnValue;value;df-generated | -| p;MultipleImpl2$IInterface;true;m;(Object);;Argument[0];ReturnValue;taint;df-generated | -| p;MultipleImpls$Strat2;true;getValue;();;Argument[this];ReturnValue;taint;df-generated | -| p;MultipleImpls$Strategy;true;doSomething;(String);;Argument[0];Argument[this];taint;df-generated | -| p;MultipleImpls$Strategy;true;doSomething;(String);;Argument[0];ReturnValue;taint;df-generated | -| p;ParamFlow;true;addTo;(String,List);;Argument[0];Argument[1].Element;taint;df-generated | -| p;ParamFlow;true;returnArrayElement;(String[]);;Argument[0].ArrayElement;ReturnValue;taint;df-generated | -| p;ParamFlow;true;returnCollectionElement;(List);;Argument[0].Element;ReturnValue;taint;df-generated | -| p;ParamFlow;true;returnIterableElement;(Iterable);;Argument[0].Element;ReturnValue;taint;df-generated | -| p;ParamFlow;true;returnIteratorElement;(Iterator);;Argument[0].Element;ReturnValue;taint;df-generated | -| p;ParamFlow;true;returnMultipleParameters;(String,String);;Argument[0];ReturnValue;taint;df-generated | -| p;ParamFlow;true;returnMultipleParameters;(String,String);;Argument[1];ReturnValue;taint;df-generated | -| p;ParamFlow;true;returnVarArgElement;(String[]);;Argument[0].ArrayElement;ReturnValue;taint;df-generated | -| p;ParamFlow;true;returnsInput;(String);;Argument[0];ReturnValue;taint;df-generated | -| p;ParamFlow;true;writeChunked;(byte[],OutputStream);;Argument[0];Argument[1];taint;df-generated | -| p;ParamFlow;true;writeChunked;(char[],OutputStream);;Argument[0];Argument[1];taint;df-generated | -| p;Pojo;false;fillIn;(List);;Argument[this];Argument[0].Element;taint;df-generated | -| p;Pojo;false;getBoxedBytes;();;Argument[this];ReturnValue;taint;df-generated | -| p;Pojo;false;getBoxedChars;();;Argument[this];ReturnValue;taint;df-generated | -| p;Pojo;false;getByteArray;();;Argument[this];ReturnValue;taint;df-generated | -| p;Pojo;false;getCharArray;();;Argument[this];ReturnValue;taint;df-generated | -| p;Pojo;false;getValue;();;Argument[this];ReturnValue;taint;df-generated | -| p;Pojo;false;setValue;(String);;Argument[0];Argument[this];taint;df-generated | -| p;PrivateFlowViaPublicInterface$SPI;true;openStream;();;Argument[this];ReturnValue;taint;df-generated | -| p;PrivateFlowViaPublicInterface;true;createAnSPI;(File);;Argument[0];ReturnValue;taint;df-generated | diff --git a/java/ql/test/utils/modelgenerator/dataflow/CaptureSummaryModels.qlref b/java/ql/test/utils/modelgenerator/dataflow/CaptureSummaryModels.qlref deleted file mode 100644 index d751f3823f3..00000000000 --- a/java/ql/test/utils/modelgenerator/dataflow/CaptureSummaryModels.qlref +++ /dev/null @@ -1 +0,0 @@ -utils/modelgenerator/CaptureSummaryModels.ql \ No newline at end of file From 51e7f3be1a0b3cd3af06ef939253f3e28676f7d0 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 6 May 2024 13:03:38 +0200 Subject: [PATCH 5/9] Java: Rename MaD to summary. --- java/ql/test/TestUtilities/InlineMadTest.qll | 9 +- .../modelgenerator/dataflow/p/Factory.java | 6 +- .../modelgenerator/dataflow/p/FinalClass.java | 2 +- .../modelgenerator/dataflow/p/FluentAPI.java | 2 +- .../dataflow/p/ImmutablePojo.java | 8 +- .../dataflow/p/InnerClasses.java | 4 +- .../dataflow/p/InnerHolder.java | 8 +- .../modelgenerator/dataflow/p/Joiner.java | 16 +- .../dataflow/p/MultipleImpl2.java | 2 +- .../dataflow/p/MultipleImpls.java | 6 +- .../modelgenerator/dataflow/p/ParamFlow.java | 22 +- .../utils/modelgenerator/dataflow/p/Pojo.java | 14 +- .../p/PrivateFlowViaPublicInterface.java | 4 +- .../typebasedflow/p/MyFunction.java | 10 +- .../typebasedflow/p/Stream.java | 404 +++++++++--------- .../typebasedflow/p/TypeBasedCollection.java | 30 +- .../typebasedflow/p/TypeBasedComplex.java | 142 +++--- .../typebasedflow/p/TypeBasedSimple.java | 58 ++- 18 files changed, 369 insertions(+), 378 deletions(-) diff --git a/java/ql/test/TestUtilities/InlineMadTest.qll b/java/ql/test/TestUtilities/InlineMadTest.qll index 64badab0dca..3e9aee7eb9e 100644 --- a/java/ql/test/TestUtilities/InlineMadTest.qll +++ b/java/ql/test/TestUtilities/InlineMadTest.qll @@ -11,21 +11,22 @@ signature module InlineMadTestConfigSig { } module InlineMadTest { - private string expects() { - Input::getComment().regexpCapture(" *(SPURIOUS-)?MaD=(.*)", 2) = result + bindingset[kind] + private string expects(string kind) { + Input::getComment().regexpCapture(" *(SPURIOUS-)?" + kind + "=(.*)", 2) = result } query predicate unexpectedSummary(string msg) { exists(string flow | flow = Input::getCapturedSummary() and - not flow = expects() and + not flow = expects("summary") and msg = "Unexpected summary found: " + flow ) } query predicate expectedSummary(string msg) { exists(string e | - e = expects() and + e = expects("summary") and not e = Input::getCapturedSummary() and msg = "Expected summary missing: " + e ) diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/Factory.java b/java/ql/test/utils/modelgenerator/dataflow/p/Factory.java index 84b55a812c9..57d26429a93 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/Factory.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/Factory.java @@ -6,12 +6,12 @@ public final class Factory { private int intValue; - // MaD=p;Factory;false;create;(String,int);;Argument[0];ReturnValue;taint;df-generated + // summary=p;Factory;false;create;(String,int);;Argument[0];ReturnValue;taint;df-generated public static Factory create(String value, int foo) { return new Factory(value, foo); } - // MaD=p;Factory;false;create;(String);;Argument[0];ReturnValue;taint;df-generated + // summary=p;Factory;false;create;(String);;Argument[0];ReturnValue;taint;df-generated public static Factory create(String value) { return new Factory(value, 0); } @@ -21,7 +21,7 @@ public final class Factory { this.intValue = intValue; } - // MaD=p;Factory;false;getValue;();;Argument[this];ReturnValue;taint;df-generated + // summary=p;Factory;false;getValue;();;Argument[this];ReturnValue;taint;df-generated public String getValue() { return value; } diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/FinalClass.java b/java/ql/test/utils/modelgenerator/dataflow/p/FinalClass.java index 5073f435233..82a39533ce1 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/FinalClass.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/FinalClass.java @@ -4,7 +4,7 @@ public final class FinalClass { private static final String C = "constant"; - // MaD=p;FinalClass;false;returnsInput;(String);;Argument[0];ReturnValue;taint;df-generated + // summary=p;FinalClass;false;returnsInput;(String);;Argument[0];ReturnValue;taint;df-generated public String returnsInput(String input) { return input; } diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/FluentAPI.java b/java/ql/test/utils/modelgenerator/dataflow/p/FluentAPI.java index 2bb2bb97604..38fbb286bb0 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/FluentAPI.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/FluentAPI.java @@ -2,7 +2,7 @@ package p; public final class FluentAPI { - // MaD=p;FluentAPI;false;returnsThis;(String);;Argument[this];ReturnValue;value;df-generated + // summary=p;FluentAPI;false;returnsThis;(String);;Argument[this];ReturnValue;value;df-generated public FluentAPI returnsThis(String input) { return this; } diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/ImmutablePojo.java b/java/ql/test/utils/modelgenerator/dataflow/p/ImmutablePojo.java index 38a9b472f62..1b39856b445 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/ImmutablePojo.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/ImmutablePojo.java @@ -6,13 +6,13 @@ public final class ImmutablePojo { private final long x; - // MaD=p;ImmutablePojo;false;ImmutablePojo;(String,int);;Argument[0];Argument[this];taint;df-generated + // summary=p;ImmutablePojo;false;ImmutablePojo;(String,int);;Argument[0];Argument[this];taint;df-generated public ImmutablePojo(String value, int x) { this.value = value; this.x = x; } - // MaD=p;ImmutablePojo;false;getValue;();;Argument[this];ReturnValue;taint;df-generated + // summary=p;ImmutablePojo;false;getValue;();;Argument[this];ReturnValue;taint;df-generated public String getValue() { return value; } @@ -21,8 +21,8 @@ public final class ImmutablePojo { return x; } - // MaD=p;ImmutablePojo;false;or;(String);;Argument[0];ReturnValue;taint;df-generated - // MaD=p;ImmutablePojo;false;or;(String);;Argument[this];ReturnValue;taint;df-generated + // summary=p;ImmutablePojo;false;or;(String);;Argument[0];ReturnValue;taint;df-generated + // summary=p;ImmutablePojo;false;or;(String);;Argument[this];ReturnValue;taint;df-generated public String or(String defaultValue) { return value != null ? value : defaultValue; } diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/InnerClasses.java b/java/ql/test/utils/modelgenerator/dataflow/p/InnerClasses.java index 54f014fec93..5b6a8427a3f 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/InnerClasses.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/InnerClasses.java @@ -9,13 +9,13 @@ public class InnerClasses { } public class CaptureMe { - // MaD=p;InnerClasses$CaptureMe;true;yesCm;(String);;Argument[0];ReturnValue;taint;df-generated + // summary=p;InnerClasses$CaptureMe;true;yesCm;(String);;Argument[0];ReturnValue;taint;df-generated public String yesCm(String input) { return input; } } - // MaD=p;InnerClasses;true;yes;(String);;Argument[0];ReturnValue;taint;df-generated + // summary=p;InnerClasses;true;yes;(String);;Argument[0];ReturnValue;taint;df-generated public String yes(String input) { return input; } diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/InnerHolder.java b/java/ql/test/utils/modelgenerator/dataflow/p/InnerHolder.java index ef872942191..e09680dad52 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/InnerHolder.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/InnerHolder.java @@ -18,22 +18,22 @@ public final class InnerHolder { private StringBuilder sb = new StringBuilder(); - // MaD=p;InnerHolder;false;setContext;(String);;Argument[0];Argument[this];taint;df-generated + // summary=p;InnerHolder;false;setContext;(String);;Argument[0];Argument[this];taint;df-generated public void setContext(String value) { context = new Context(value); } - // MaD=p;InnerHolder;false;explicitSetContext;(String);;Argument[0];Argument[this];taint;df-generated + // summary=p;InnerHolder;false;explicitSetContext;(String);;Argument[0];Argument[this];taint;df-generated public void explicitSetContext(String value) { this.context = new Context(value); } - // MaD=p;InnerHolder;false;append;(String);;Argument[0];Argument[this];taint;df-generated + // summary=p;InnerHolder;false;append;(String);;Argument[0];Argument[this];taint;df-generated public void append(String value) { sb.append(value); } - // MaD=p;InnerHolder;false;getValue;();;Argument[this];ReturnValue;taint;df-generated + // summary=p;InnerHolder;false;getValue;();;Argument[this];ReturnValue;taint;df-generated public String getValue() { return context.getValue(); } diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/Joiner.java b/java/ql/test/utils/modelgenerator/dataflow/p/Joiner.java index daa939ebe51..60edb0fb71e 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/Joiner.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/Joiner.java @@ -12,14 +12,14 @@ public final class Joiner { private int len; private String emptyValue; - // MaD=p;Joiner;false;Joiner;(CharSequence);;Argument[0];Argument[this];taint;df-generated + // summary=p;Joiner;false;Joiner;(CharSequence);;Argument[0];Argument[this];taint;df-generated public Joiner(CharSequence delimiter) { this(delimiter, "", ""); } - // MaD=p;Joiner;false;Joiner;(CharSequence,CharSequence,CharSequence);;Argument[0];Argument[this];taint;df-generated - // MaD=p;Joiner;false;Joiner;(CharSequence,CharSequence,CharSequence);;Argument[1];Argument[this];taint;df-generated - // MaD=p;Joiner;false;Joiner;(CharSequence,CharSequence,CharSequence);;Argument[2];Argument[this];taint;df-generated + // summary=p;Joiner;false;Joiner;(CharSequence,CharSequence,CharSequence);;Argument[0];Argument[this];taint;df-generated + // summary=p;Joiner;false;Joiner;(CharSequence,CharSequence,CharSequence);;Argument[1];Argument[this];taint;df-generated + // summary=p;Joiner;false;Joiner;(CharSequence,CharSequence,CharSequence);;Argument[2];Argument[this];taint;df-generated public Joiner(CharSequence delimiter, CharSequence prefix, CharSequence suffix) { Objects.requireNonNull(prefix, "The prefix must not be null"); Objects.requireNonNull(delimiter, "The delimiter must not be null"); @@ -30,8 +30,8 @@ public final class Joiner { checkAddLength(0, 0); } - // MaD=p;Joiner;false;setEmptyValue;(CharSequence);;Argument[0];Argument[this];taint;df-generated - // MaD=p;Joiner;false;setEmptyValue;(CharSequence);;Argument[this];ReturnValue;value;df-generated + // summary=p;Joiner;false;setEmptyValue;(CharSequence);;Argument[0];Argument[this];taint;df-generated + // summary=p;Joiner;false;setEmptyValue;(CharSequence);;Argument[this];ReturnValue;value;df-generated public Joiner setEmptyValue(CharSequence emptyValue) { this.emptyValue = Objects.requireNonNull(emptyValue, "The empty value must not be null").toString(); @@ -70,7 +70,7 @@ public final class Joiner { return new String(chars); } - // MaD=p;Joiner;false;add;(CharSequence);;Argument[this];ReturnValue;value;df-generated + // summary=p;Joiner;false;add;(CharSequence);;Argument[this];ReturnValue;value;df-generated public Joiner add(CharSequence newElement) { final String elt = String.valueOf(newElement); if (elts == null) { @@ -93,7 +93,7 @@ public final class Joiner { return (int) newLen; } - // MaD=p;Joiner;false;merge;(Joiner);;Argument[this];ReturnValue;value;df-generated + // summary=p;Joiner;false;merge;(Joiner);;Argument[this];ReturnValue;value;df-generated public Joiner merge(Joiner other) { Objects.requireNonNull(other); if (other.elts == null) { diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/MultipleImpl2.java b/java/ql/test/utils/modelgenerator/dataflow/p/MultipleImpl2.java index 7c2e2ed9211..dc67d0dfe6c 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/MultipleImpl2.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/MultipleImpl2.java @@ -6,7 +6,7 @@ class MultipleImpl2 { // This is used to test that we only generate a summary model and // not neutral summary model for `IInterface.m`. public interface IInterface { - // MaD=p;MultipleImpl2$IInterface;true;m;(Object);;Argument[0];ReturnValue;taint;df-generated + // summary=p;MultipleImpl2$IInterface;true;m;(Object);;Argument[0];ReturnValue;taint;df-generated Object m(Object value); } diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/MultipleImpls.java b/java/ql/test/utils/modelgenerator/dataflow/p/MultipleImpls.java index 8cdde304bd5..8fccdf76ab7 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/MultipleImpls.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/MultipleImpls.java @@ -5,8 +5,8 @@ import java.util.concurrent.Callable; public class MultipleImpls { public static interface Strategy { - // MaD=p;MultipleImpls$Strategy;true;doSomething;(String);;Argument[0];Argument[this];taint;df-generated - // MaD=p;MultipleImpls$Strategy;true;doSomething;(String);;Argument[0];ReturnValue;taint;df-generated + // summary=p;MultipleImpls$Strategy;true;doSomething;(String);;Argument[0];Argument[this];taint;df-generated + // summary=p;MultipleImpls$Strategy;true;doSomething;(String);;Argument[0];ReturnValue;taint;df-generated String doSomething(String value); } @@ -33,7 +33,7 @@ public class MultipleImpls { return "none"; } - // MaD=p;MultipleImpls$Strat2;true;getValue;();;Argument[this];ReturnValue;taint;df-generated + // summary=p;MultipleImpls$Strat2;true;getValue;();;Argument[this];ReturnValue;taint;df-generated public String getValue() { return this.foo; } diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/ParamFlow.java b/java/ql/test/utils/modelgenerator/dataflow/p/ParamFlow.java index 7d9dac157c2..5c47e292a6b 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/ParamFlow.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/ParamFlow.java @@ -7,7 +7,7 @@ import java.util.List; public class ParamFlow { - // MaD=p;ParamFlow;true;returnsInput;(String);;Argument[0];ReturnValue;taint;df-generated + // summary=p;ParamFlow;true;returnsInput;(String);;Argument[0];ReturnValue;taint;df-generated public String returnsInput(String input) { return input; } @@ -16,8 +16,8 @@ public class ParamFlow { return input.length(); } - // MaD=p;ParamFlow;true;returnMultipleParameters;(String,String);;Argument[0];ReturnValue;taint;df-generated - // MaD=p;ParamFlow;true;returnMultipleParameters;(String,String);;Argument[1];ReturnValue;taint;df-generated + // summary=p;ParamFlow;true;returnMultipleParameters;(String,String);;Argument[0];ReturnValue;taint;df-generated + // summary=p;ParamFlow;true;returnMultipleParameters;(String,String);;Argument[1];ReturnValue;taint;df-generated public String returnMultipleParameters(String one, String two) { if (System.currentTimeMillis() > 100) { return two; @@ -25,27 +25,27 @@ public class ParamFlow { return one; } - // MaD=p;ParamFlow;true;returnArrayElement;(String[]);;Argument[0].ArrayElement;ReturnValue;taint;df-generated + // summary=p;ParamFlow;true;returnArrayElement;(String[]);;Argument[0].ArrayElement;ReturnValue;taint;df-generated public String returnArrayElement(String[] input) { return input[0]; } - // MaD=p;ParamFlow;true;returnVarArgElement;(String[]);;Argument[0].ArrayElement;ReturnValue;taint;df-generated + // summary=p;ParamFlow;true;returnVarArgElement;(String[]);;Argument[0].ArrayElement;ReturnValue;taint;df-generated public String returnVarArgElement(String... input) { return input[0]; } - // MaD=p;ParamFlow;true;returnCollectionElement;(List);;Argument[0].Element;ReturnValue;taint;df-generated + // summary=p;ParamFlow;true;returnCollectionElement;(List);;Argument[0].Element;ReturnValue;taint;df-generated public String returnCollectionElement(List input) { return input.get(0); } - // MaD=p;ParamFlow;true;returnIteratorElement;(Iterator);;Argument[0].Element;ReturnValue;taint;df-generated + // summary=p;ParamFlow;true;returnIteratorElement;(Iterator);;Argument[0].Element;ReturnValue;taint;df-generated public String returnIteratorElement(Iterator input) { return input.next(); } - // MaD=p;ParamFlow;true;returnIterableElement;(Iterable);;Argument[0].Element;ReturnValue;taint;df-generated + // summary=p;ParamFlow;true;returnIterableElement;(Iterable);;Argument[0].Element;ReturnValue;taint;df-generated public String returnIterableElement(Iterable input) { return input.iterator().next(); } @@ -54,17 +54,17 @@ public class ParamFlow { return input; } - // MaD=p;ParamFlow;true;writeChunked;(byte[],OutputStream);;Argument[0];Argument[1];taint;df-generated + // summary=p;ParamFlow;true;writeChunked;(byte[],OutputStream);;Argument[0];Argument[1];taint;df-generated public void writeChunked(byte[] data, OutputStream output) throws IOException { output.write(data, 0, data.length); } - // MaD=p;ParamFlow;true;writeChunked;(char[],OutputStream);;Argument[0];Argument[1];taint;df-generated + // summary=p;ParamFlow;true;writeChunked;(char[],OutputStream);;Argument[0];Argument[1];taint;df-generated public void writeChunked(char[] data, OutputStream output) throws IOException { output.write(String.valueOf(data).getBytes(), 0, data.length); } - // MaD=p;ParamFlow;true;addTo;(String,List);;Argument[0];Argument[1].Element;taint;df-generated + // summary=p;ParamFlow;true;addTo;(String,List);;Argument[0];Argument[1].Element;taint;df-generated public void addTo(String data, List target) { target.add(data); } diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/Pojo.java b/java/ql/test/utils/modelgenerator/dataflow/p/Pojo.java index 15fbda5bc79..524e448ef81 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/Pojo.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/Pojo.java @@ -30,12 +30,12 @@ public final class Pojo { private List charList = Arrays.asList('a', 'b', 'c'); private Byte[] byteObjectArray = new Byte[] {1, 2, 3}; - // MaD=p;Pojo;false;getValue;();;Argument[this];ReturnValue;taint;df-generated + // summary=p;Pojo;false;getValue;();;Argument[this];ReturnValue;taint;df-generated public String getValue() { return value; } - // MaD=p;Pojo;false;setValue;(String);;Argument[0];Argument[this];taint;df-generated + // summary=p;Pojo;false;setValue;(String);;Argument[0];Argument[this];taint;df-generated public void setValue(String value) { this.value = value; } @@ -57,12 +57,12 @@ public final class Pojo { return new int[] {intValue}; } - // MaD=p;Pojo;false;getCharArray;();;Argument[this];ReturnValue;taint;df-generated + // summary=p;Pojo;false;getCharArray;();;Argument[this];ReturnValue;taint;df-generated public char[] getCharArray() { return charArray; } - // MaD=p;Pojo;false;getByteArray;();;Argument[this];ReturnValue;taint;df-generated + // summary=p;Pojo;false;getByteArray;();;Argument[this];ReturnValue;taint;df-generated public byte[] getByteArray() { return byteArray; } @@ -79,12 +79,12 @@ public final class Pojo { return List.of(Integer.valueOf(intValue)); } - // MaD=p;Pojo;false;getBoxedChars;();;Argument[this];ReturnValue;taint;df-generated + // summary=p;Pojo;false;getBoxedChars;();;Argument[this];ReturnValue;taint;df-generated public List getBoxedChars() { return charList; } - // MaD=p;Pojo;false;getBoxedBytes;();;Argument[this];ReturnValue;taint;df-generated + // summary=p;Pojo;false;getBoxedBytes;();;Argument[this];ReturnValue;taint;df-generated public Byte[] getBoxedBytes() { return byteObjectArray; } @@ -97,7 +97,7 @@ public final class Pojo { return new BigDecimal(value); } - // MaD=p;Pojo;false;fillIn;(List);;Argument[this];Argument[0].Element;taint;df-generated + // summary=p;Pojo;false;fillIn;(List);;Argument[this];Argument[0].Element;taint;df-generated public void fillIn(List target) { target.add(value); } diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/PrivateFlowViaPublicInterface.java b/java/ql/test/utils/modelgenerator/dataflow/p/PrivateFlowViaPublicInterface.java index 13a2897f08a..6b5dbca3e11 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/PrivateFlowViaPublicInterface.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/PrivateFlowViaPublicInterface.java @@ -12,7 +12,7 @@ public class PrivateFlowViaPublicInterface { } public static interface SPI { - // MaD=p;PrivateFlowViaPublicInterface$SPI;true;openStream;();;Argument[this];ReturnValue;taint;df-generated + // summary=p;PrivateFlowViaPublicInterface$SPI;true;openStream;();;Argument[this];ReturnValue;taint;df-generated OutputStream openStream() throws IOException; default OutputStream openStreamNone() throws IOException { @@ -50,7 +50,7 @@ public class PrivateFlowViaPublicInterface { } } - // MaD=p;PrivateFlowViaPublicInterface;true;createAnSPI;(File);;Argument[0];ReturnValue;taint;df-generated + // summary=p;PrivateFlowViaPublicInterface;true;createAnSPI;(File);;Argument[0];ReturnValue;taint;df-generated public static SPI createAnSPI(File file) { return new PrivateImplWithSink(file); } diff --git a/java/ql/test/utils/modelgenerator/typebasedflow/p/MyFunction.java b/java/ql/test/utils/modelgenerator/typebasedflow/p/MyFunction.java index 04683952f83..e3589bf5f6c 100644 --- a/java/ql/test/utils/modelgenerator/typebasedflow/p/MyFunction.java +++ b/java/ql/test/utils/modelgenerator/typebasedflow/p/MyFunction.java @@ -3,8 +3,8 @@ package p; @FunctionalInterface public interface MyFunction { - // MaD=p;MyFunction;true;apply;(Object,Object);;Argument[this].SyntheticField[ArgType2];ReturnValue;value;tb-generated - // MaD=p;MyFunction;true;apply;(Object,Object);;Argument[0];Argument[this].SyntheticField[ArgType0];value;tb-generated - // MaD=p;MyFunction;true;apply;(Object,Object);;Argument[1];Argument[this].SyntheticField[ArgType1];value;tb-generated - T3 apply(T1 x, T2 y); -} \ No newline at end of file + // summary=p;MyFunction;true;apply;(Object,Object);;Argument[this].SyntheticField[ArgType2];ReturnValue;value;tb-generated + // summary=p;MyFunction;true;apply;(Object,Object);;Argument[0];Argument[this].SyntheticField[ArgType0];value;tb-generated + // summary=p;MyFunction;true;apply;(Object,Object);;Argument[1];Argument[this].SyntheticField[ArgType1];value;tb-generated + T3 apply(T1 x, T2 y); +} diff --git a/java/ql/test/utils/modelgenerator/typebasedflow/p/Stream.java b/java/ql/test/utils/modelgenerator/typebasedflow/p/Stream.java index 86d25088645..8e99fc7ca7c 100644 --- a/java/ql/test/utils/modelgenerator/typebasedflow/p/Stream.java +++ b/java/ql/test/utils/modelgenerator/typebasedflow/p/Stream.java @@ -2,246 +2,244 @@ package p; import java.util.*; import java.util.function.*; -import java.util.stream.LongStream; -import java.util.stream.IntStream; -import java.util.stream.DoubleStream; import java.util.stream.Collector; +import java.util.stream.DoubleStream; +import java.util.stream.IntStream; +import java.util.stream.LongStream; -/** - * This is a stub implementation of the Java Stream API. - */ +/** This is a stub implementation of the Java Stream API. */ public class Stream { - // MaD=p;Stream;true;iterator;();;Argument[this].Element;ReturnValue.Element;value;tb-generated - public Iterator iterator() { - return null; - } + // summary=p;Stream;true;iterator;();;Argument[this].Element;ReturnValue.Element;value;tb-generated + public Iterator iterator() { + return null; + } - // MaD=p;Stream;true;allMatch;(Predicate);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated - public boolean allMatch(Predicate predicate) { - return false; - } + // summary=p;Stream;true;allMatch;(Predicate);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated + public boolean allMatch(Predicate predicate) { + return false; + } - // MaD=p;Stream;true;collect;(Supplier,BiConsumer,BiConsumer);;Argument[this].Element;Argument[1].Parameter[1];value;tb-generated - // MaD=p;Stream;true;collect;(Supplier,BiConsumer,BiConsumer);;Argument[0].ReturnValue;Argument[1].Parameter[0];value;tb-generated - // MaD=p;Stream;true;collect;(Supplier,BiConsumer,BiConsumer);;Argument[0].ReturnValue;Argument[2].Parameter[0];value;tb-generated - // MaD=p;Stream;true;collect;(Supplier,BiConsumer,BiConsumer);;Argument[0].ReturnValue;Argument[2].Parameter[1];value;tb-generated - // MaD=p;Stream;true;collect;(Supplier,BiConsumer,BiConsumer);;Argument[0].ReturnValue;ReturnValue;value;tb-generated - public R collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner) { - return null; - } + // summary=p;Stream;true;collect;(Supplier,BiConsumer,BiConsumer);;Argument[this].Element;Argument[1].Parameter[1];value;tb-generated + // summary=p;Stream;true;collect;(Supplier,BiConsumer,BiConsumer);;Argument[0].ReturnValue;Argument[1].Parameter[0];value;tb-generated + // summary=p;Stream;true;collect;(Supplier,BiConsumer,BiConsumer);;Argument[0].ReturnValue;Argument[2].Parameter[0];value;tb-generated + // summary=p;Stream;true;collect;(Supplier,BiConsumer,BiConsumer);;Argument[0].ReturnValue;Argument[2].Parameter[1];value;tb-generated + // summary=p;Stream;true;collect;(Supplier,BiConsumer,BiConsumer);;Argument[0].ReturnValue;ReturnValue;value;tb-generated + public R collect( + Supplier supplier, BiConsumer accumulator, BiConsumer combiner) { + return null; + } - // Collector is not a functional interface, so this is not supported - public R collect(Collector collector) { - return null; - } + // Collector is not a functional interface, so this is not supported + public R collect(Collector collector) { + return null; + } - // MaD=p;Stream;true;concat;(Stream,Stream);;Argument[0].Element;ReturnValue.Element;value;tb-generated - // MaD=p;Stream;true;concat;(Stream,Stream);;Argument[1].Element;ReturnValue.Element;value;tb-generated - public static Stream concat(Stream a, Stream b) { - return null; - } + // summary=p;Stream;true;concat;(Stream,Stream);;Argument[0].Element;ReturnValue.Element;value;tb-generated + // summary=p;Stream;true;concat;(Stream,Stream);;Argument[1].Element;ReturnValue.Element;value;tb-generated + public static Stream concat(Stream a, Stream b) { + return null; + } - // MaD=p;Stream;true;distinct;();;Argument[this].Element;ReturnValue.Element;value;tb-generated - public Stream distinct() { - return null; - } + // summary=p;Stream;true;distinct;();;Argument[this].Element;ReturnValue.Element;value;tb-generated + public Stream distinct() { + return null; + } - public static Stream empty() { - return null; - } + public static Stream empty() { + return null; + } - // MaD=p;Stream;true;filter;(Predicate);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated - // MaD=p;Stream;true;filter;(Predicate);;Argument[this].Element;ReturnValue.Element;value;tb-generated - public Stream filter(Predicate predicate) { - return null; - } + // summary=p;Stream;true;filter;(Predicate);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated + // summary=p;Stream;true;filter;(Predicate);;Argument[this].Element;ReturnValue.Element;value;tb-generated + public Stream filter(Predicate predicate) { + return null; + } - // MaD=p;Stream;true;findAny;();;Argument[this].Element;ReturnValue.SyntheticField[ArgType0];value;tb-generated - public Optional findAny() { - return null; - } + // summary=p;Stream;true;findAny;();;Argument[this].Element;ReturnValue.SyntheticField[ArgType0];value;tb-generated + public Optional findAny() { + return null; + } - // MaD=p;Stream;true;findFirst;();;Argument[this].Element;ReturnValue.SyntheticField[ArgType0];value;tb-generated - public Optional findFirst() { - return null; - } + // summary=p;Stream;true;findFirst;();;Argument[this].Element;ReturnValue.SyntheticField[ArgType0];value;tb-generated + public Optional findFirst() { + return null; + } - // MaD=p;Stream;true;flatMap;(Function);;Argument[0].ReturnValue.Element;ReturnValue.Element;value;tb-generated - // MaD=p;Stream;true;flatMap;(Function);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated - public Stream flatMap(Function> mapper) { - return null; - } + // summary=p;Stream;true;flatMap;(Function);;Argument[0].ReturnValue.Element;ReturnValue.Element;value;tb-generated + // summary=p;Stream;true;flatMap;(Function);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated + public Stream flatMap(Function> mapper) { + return null; + } - // MaD=p;Stream;true;flatMapToDouble;(Function);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated - public DoubleStream flatMapToDouble(Function mapper) { - return null; - } + // summary=p;Stream;true;flatMapToDouble;(Function);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated + public DoubleStream flatMapToDouble(Function mapper) { + return null; + } - // MaD=p;Stream;true;flatMapToInt;(Function);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated - public IntStream flatMapToInt(Function mapper) { - return null; - } + // summary=p;Stream;true;flatMapToInt;(Function);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated + public IntStream flatMapToInt(Function mapper) { + return null; + } - // MaD=p;Stream;true;flatMapToLong;(Function);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated - public LongStream flatMapToLong(Function mapper) { - return null; - } + // summary=p;Stream;true;flatMapToLong;(Function);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated + public LongStream flatMapToLong(Function mapper) { + return null; + } - // MaD=p;Stream;true;forEach;(Consumer);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated - public void forEach(Consumer action) { - } + // summary=p;Stream;true;forEach;(Consumer);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated + public void forEach(Consumer action) {} - // MaD=p;Stream;true;forEachOrdered;(Consumer);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated - public void forEachOrdered(Consumer action) { - } + // summary=p;Stream;true;forEachOrdered;(Consumer);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated + public void forEachOrdered(Consumer action) {} - // MaD=p;Stream;true;generate;(Supplier);;Argument[0].ReturnValue;ReturnValue.Element;value;tb-generated - public static Stream generate(Supplier s) { - return null; - } + // summary=p;Stream;true;generate;(Supplier);;Argument[0].ReturnValue;ReturnValue.Element;value;tb-generated + public static Stream generate(Supplier s) { + return null; + } - // MaD=p;Stream;true;iterate;(Object,UnaryOperator);;Argument[0];Argument[1].Parameter[0];value;tb-generated - // MaD=p;Stream;true;iterate;(Object,UnaryOperator);;Argument[0];ReturnValue.Element;value;tb-generated - // MaD=p;Stream;true;iterate;(Object,UnaryOperator);;Argument[1].ReturnValue;Argument[1].Parameter[0];value;tb-generated - // MaD=p;Stream;true;iterate;(Object,UnaryOperator);;Argument[1].ReturnValue;ReturnValue.Element;value;tb-generated - public static Stream iterate(T seed, UnaryOperator f) { - return null; - } + // summary=p;Stream;true;iterate;(Object,UnaryOperator);;Argument[0];Argument[1].Parameter[0];value;tb-generated + // summary=p;Stream;true;iterate;(Object,UnaryOperator);;Argument[0];ReturnValue.Element;value;tb-generated + // summary=p;Stream;true;iterate;(Object,UnaryOperator);;Argument[1].ReturnValue;Argument[1].Parameter[0];value;tb-generated + // summary=p;Stream;true;iterate;(Object,UnaryOperator);;Argument[1].ReturnValue;ReturnValue.Element;value;tb-generated + public static Stream iterate(T seed, UnaryOperator f) { + return null; + } - // MaD=p;Stream;true;limit;(long);;Argument[this].Element;ReturnValue.Element;value;tb-generated - public Stream limit(long maxSize) { - return null; - } + // summary=p;Stream;true;limit;(long);;Argument[this].Element;ReturnValue.Element;value;tb-generated + public Stream limit(long maxSize) { + return null; + } - // MaD=p;Stream;true;map;(Function);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated - // MaD=p;Stream;true;map;(Function);;Argument[0].ReturnValue;ReturnValue.Element;value;tb-generated - public Stream map(Function mapper) { - return null; - } + // summary=p;Stream;true;map;(Function);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated + // summary=p;Stream;true;map;(Function);;Argument[0].ReturnValue;ReturnValue.Element;value;tb-generated + public Stream map(Function mapper) { + return null; + } - // MaD=p;Stream;true;mapToDouble;(ToDoubleFunction);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated - public DoubleStream mapToDouble(ToDoubleFunction mapper) { - return null; - } + // summary=p;Stream;true;mapToDouble;(ToDoubleFunction);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated + public DoubleStream mapToDouble(ToDoubleFunction mapper) { + return null; + } - // MaD=p;Stream;true;mapToInt;(ToIntFunction);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated - public IntStream mapToInt(ToIntFunction mapper) { - return null; - } + // summary=p;Stream;true;mapToInt;(ToIntFunction);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated + public IntStream mapToInt(ToIntFunction mapper) { + return null; + } - // MaD=p;Stream;true;mapToLong;(ToLongFunction);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated - public LongStream mapToLong(ToLongFunction mapper) { - return null; - } + // summary=p;Stream;true;mapToLong;(ToLongFunction);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated + public LongStream mapToLong(ToLongFunction mapper) { + return null; + } - // MaD=p;Stream;true;max;(Comparator);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated - // MaD=p;Stream;true;max;(Comparator);;Argument[this].Element;Argument[0].Parameter[1];value;tb-generated - // MaD=p;Stream;true;max;(Comparator);;Argument[this].Element;ReturnValue.SyntheticField[ArgType0];value;tb-generated - public Optional max(Comparator comparator) { - return null; - } + // summary=p;Stream;true;max;(Comparator);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated + // summary=p;Stream;true;max;(Comparator);;Argument[this].Element;Argument[0].Parameter[1];value;tb-generated + // summary=p;Stream;true;max;(Comparator);;Argument[this].Element;ReturnValue.SyntheticField[ArgType0];value;tb-generated + public Optional max(Comparator comparator) { + return null; + } - // MaD=p;Stream;true;min;(Comparator);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated - // MaD=p;Stream;true;min;(Comparator);;Argument[this].Element;Argument[0].Parameter[1];value;tb-generated - // MaD=p;Stream;true;min;(Comparator);;Argument[this].Element;ReturnValue.SyntheticField[ArgType0];value;tb-generated - public Optional min(Comparator comparator) { - return null; - } + // summary=p;Stream;true;min;(Comparator);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated + // summary=p;Stream;true;min;(Comparator);;Argument[this].Element;Argument[0].Parameter[1];value;tb-generated + // summary=p;Stream;true;min;(Comparator);;Argument[this].Element;ReturnValue.SyntheticField[ArgType0];value;tb-generated + public Optional min(Comparator comparator) { + return null; + } - // MaD=p;Stream;true;noneMatch;(Predicate);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated - public boolean noneMatch(Predicate predicate) { - return false; - } + // summary=p;Stream;true;noneMatch;(Predicate);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated + public boolean noneMatch(Predicate predicate) { + return false; + } - // MaD=p;Stream;true;of;(Object[]);;Argument[0].ArrayElement;ReturnValue.Element;value;tb-generated - public static Stream of(T... t) { - return null; - } + // summary=p;Stream;true;of;(Object[]);;Argument[0].ArrayElement;ReturnValue.Element;value;tb-generated + public static Stream of(T... t) { + return null; + } - // MaD=p;Stream;true;of;(Object);;Argument[0];ReturnValue.Element;value;tb-generated - public static Stream of(T t) { - return null; - } + // summary=p;Stream;true;of;(Object);;Argument[0];ReturnValue.Element;value;tb-generated + public static Stream of(T t) { + return null; + } - // MaD=p;Stream;true;peek;(Consumer);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated - // MaD=p;Stream;true;peek;(Consumer);;Argument[this].Element;ReturnValue.Element;value;tb-generated - public Stream peek(Consumer action) { - return null; - } + // summary=p;Stream;true;peek;(Consumer);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated + // summary=p;Stream;true;peek;(Consumer);;Argument[this].Element;ReturnValue.Element;value;tb-generated + public Stream peek(Consumer action) { + return null; + } - // The generated models are only partially correct. - // MaD=p;Stream;true;reduce;(BinaryOperator);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated - // MaD=p;Stream;true;reduce;(BinaryOperator);;Argument[this].Element;Argument[0].Parameter[1];value;tb-generated - // MaD=p;Stream;true;reduce;(BinaryOperator);;Argument[this].Element;ReturnValue.SyntheticField[ArgType0];value;tb-generated - // MaD=p;Stream;true;reduce;(BinaryOperator);;Argument[0].ReturnValue;Argument[0].Parameter[0];value;tb-generated - // MaD=p;Stream;true;reduce;(BinaryOperator);;Argument[0].ReturnValue;Argument[0].Parameter[1];value;tb-generated - // MaD=p;Stream;true;reduce;(BinaryOperator);;Argument[0].ReturnValue;ReturnValue.SyntheticField[ArgType0];value;tb-generated - // SPURIOUS-MaD=p;Stream;true;reduce;(BinaryOperator);;Argument[0].ReturnValue;Argument[this].Element;value;tb-generated - public Optional reduce(BinaryOperator accumulator) { - return null; - } + // The generated models are only partially correct. + // summary=p;Stream;true;reduce;(BinaryOperator);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated + // summary=p;Stream;true;reduce;(BinaryOperator);;Argument[this].Element;Argument[0].Parameter[1];value;tb-generated + // summary=p;Stream;true;reduce;(BinaryOperator);;Argument[this].Element;ReturnValue.SyntheticField[ArgType0];value;tb-generated + // summary=p;Stream;true;reduce;(BinaryOperator);;Argument[0].ReturnValue;Argument[0].Parameter[0];value;tb-generated + // summary=p;Stream;true;reduce;(BinaryOperator);;Argument[0].ReturnValue;Argument[0].Parameter[1];value;tb-generated + // summary=p;Stream;true;reduce;(BinaryOperator);;Argument[0].ReturnValue;ReturnValue.SyntheticField[ArgType0];value;tb-generated + // SPURIOUS-summary=p;Stream;true;reduce;(BinaryOperator);;Argument[0].ReturnValue;Argument[this].Element;value;tb-generated + public Optional reduce(BinaryOperator accumulator) { + return null; + } - // The generated models are only partially correct. - // MaD=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[this].Element;Argument[1].Parameter[0];value;tb-generated - // MaD=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[this].Element;Argument[1].Parameter[1];value;tb-generated - // MaD=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[0];Argument[1].Parameter[0];value;tb-generated - // MaD=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[0];Argument[1].Parameter[1];value;tb-generated - // MaD=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[0];ReturnValue;value;tb-generated - // MaD=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[1].ReturnValue;Argument[1].Parameter[0];value;tb-generated - // MaD=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[1].ReturnValue;Argument[1].Parameter[1];value;tb-generated - // MaD=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[1].ReturnValue;ReturnValue;value;tb-generated - // SPURIOUS-MaD=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[this].Element;ReturnValue;value;tb-generated - // SPURIOUS-MaD=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[0];Argument[this].Element;value;tb-generated - // SPURIOUS-MaD=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[1].ReturnValue;Argument[this].Element;value;tb-generated - public T reduce(T identity, BinaryOperator accumulator) { - return null; - } + // The generated models are only partially correct. + // summary=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[this].Element;Argument[1].Parameter[0];value;tb-generated + // summary=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[this].Element;Argument[1].Parameter[1];value;tb-generated + // summary=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[0];Argument[1].Parameter[0];value;tb-generated + // summary=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[0];Argument[1].Parameter[1];value;tb-generated + // summary=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[0];ReturnValue;value;tb-generated + // summary=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[1].ReturnValue;Argument[1].Parameter[0];value;tb-generated + // summary=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[1].ReturnValue;Argument[1].Parameter[1];value;tb-generated + // summary=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[1].ReturnValue;ReturnValue;value;tb-generated + // SPURIOUS-summary=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[this].Element;ReturnValue;value;tb-generated + // SPURIOUS-summary=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[0];Argument[this].Element;value;tb-generated + // SPURIOUS-summary=p;Stream;true;reduce;(Object,BinaryOperator);;Argument[1].ReturnValue;Argument[this].Element;value;tb-generated + public T reduce(T identity, BinaryOperator accumulator) { + return null; + } - // MaD=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[this].Element;Argument[1].Parameter[1];value;tb-generated - // MaD=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[0];Argument[1].Parameter[0];value;tb-generated - // MaD=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[0];Argument[2].Parameter[0];value;tb-generated - // MaD=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[0];Argument[2].Parameter[1];value;tb-generated - // MaD=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[0];ReturnValue;value;tb-generated - // MaD=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[1].ReturnValue;Argument[1].Parameter[0];value;tb-generated - // MaD=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[1].ReturnValue;Argument[2].Parameter[0];value;tb-generated - // MaD=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[1].ReturnValue;Argument[2].Parameter[1];value;tb-generated - // MaD=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[1].ReturnValue;ReturnValue;value;tb-generated - // MaD=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[2].ReturnValue;Argument[1].Parameter[0];value;tb-generated - // MaD=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[2].ReturnValue;Argument[2].Parameter[0];value;tb-generated - // MaD=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[2].ReturnValue;Argument[2].Parameter[1];value;tb-generated - // MaD=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[2].ReturnValue;ReturnValue;value;tb-generated - public U reduce(U identity, BiFunction accumulator, BinaryOperator combiner) { - return null; - } + // summary=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[this].Element;Argument[1].Parameter[1];value;tb-generated + // summary=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[0];Argument[1].Parameter[0];value;tb-generated + // summary=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[0];Argument[2].Parameter[0];value;tb-generated + // summary=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[0];Argument[2].Parameter[1];value;tb-generated + // summary=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[0];ReturnValue;value;tb-generated + // summary=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[1].ReturnValue;Argument[1].Parameter[0];value;tb-generated + // summary=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[1].ReturnValue;Argument[2].Parameter[0];value;tb-generated + // summary=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[1].ReturnValue;Argument[2].Parameter[1];value;tb-generated + // summary=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[1].ReturnValue;ReturnValue;value;tb-generated + // summary=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[2].ReturnValue;Argument[1].Parameter[0];value;tb-generated + // summary=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[2].ReturnValue;Argument[2].Parameter[0];value;tb-generated + // summary=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[2].ReturnValue;Argument[2].Parameter[1];value;tb-generated + // summary=p;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[2].ReturnValue;ReturnValue;value;tb-generated + public U reduce( + U identity, BiFunction accumulator, BinaryOperator combiner) { + return null; + } - // MaD=p;Stream;true;skip;(long);;Argument[this].Element;ReturnValue.Element;value;tb-generated - public Stream skip(long n) { - return null; - } + // summary=p;Stream;true;skip;(long);;Argument[this].Element;ReturnValue.Element;value;tb-generated + public Stream skip(long n) { + return null; + } - // MaD=p;Stream;true;sorted;();;Argument[this].Element;ReturnValue.Element;value;tb-generated - public Stream sorted() { - return null; - } + // summary=p;Stream;true;sorted;();;Argument[this].Element;ReturnValue.Element;value;tb-generated + public Stream sorted() { + return null; + } - // MaD=p;Stream;true;sorted;(Comparator);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated - // MaD=p;Stream;true;sorted;(Comparator);;Argument[this].Element;Argument[0].Parameter[1];value;tb-generated - // MaD=p;Stream;true;sorted;(Comparator);;Argument[this].Element;ReturnValue.Element;value;tb-generated - public Stream sorted(Comparator comparator) { - return null; - } + // summary=p;Stream;true;sorted;(Comparator);;Argument[this].Element;Argument[0].Parameter[0];value;tb-generated + // summary=p;Stream;true;sorted;(Comparator);;Argument[this].Element;Argument[0].Parameter[1];value;tb-generated + // summary=p;Stream;true;sorted;(Comparator);;Argument[this].Element;ReturnValue.Element;value;tb-generated + public Stream sorted(Comparator comparator) { + return null; + } - // Models can never be generated correctly based on the type information - // as it involves downcasting. - public Object[] toArray() { - return null; - } + // Models can never be generated correctly based on the type information + // as it involves downcasting. + public Object[] toArray() { + return null; + } - // The generated result is only partially correct as there is no mentioning of - // the type T in the method definition. - // MaD=p;Stream;true;toArray;(IntFunction);;Argument[0].ReturnValue.ArrayElement;ReturnValue.ArrayElement;value;tb-generated - public A[] toArray(IntFunction generator) { - return null; - } -} \ No newline at end of file + // The generated result is only partially correct as there is no mentioning of + // the type T in the method definition. + // summary=p;Stream;true;toArray;(IntFunction);;Argument[0].ReturnValue.ArrayElement;ReturnValue.ArrayElement;value;tb-generated + public A[] toArray(IntFunction generator) { + return null; + } +} diff --git a/java/ql/test/utils/modelgenerator/typebasedflow/p/TypeBasedCollection.java b/java/ql/test/utils/modelgenerator/typebasedflow/p/TypeBasedCollection.java index b1c95dc415a..e66189e7ded 100644 --- a/java/ql/test/utils/modelgenerator/typebasedflow/p/TypeBasedCollection.java +++ b/java/ql/test/utils/modelgenerator/typebasedflow/p/TypeBasedCollection.java @@ -1,25 +1,23 @@ package p; -import java.util.List; import java.util.ArrayList; +import java.util.List; public class TypeBasedCollection extends ArrayList { - // MaD=p;TypeBasedCollection;true;addT;(Object);;Argument[0];Argument[this].Element;value;tb-generated - public void addT(T x) { - } + // summary=p;TypeBasedCollection;true;addT;(Object);;Argument[0];Argument[this].Element;value;tb-generated + public void addT(T x) {} - // MaD=p;TypeBasedCollection;true;addManyT;(List);;Argument[0].Element;Argument[this].Element;value;tb-generated - public void addManyT(List xs) { - } + // summary=p;TypeBasedCollection;true;addManyT;(List);;Argument[0].Element;Argument[this].Element;value;tb-generated + public void addManyT(List xs) {} - // MaD=p;TypeBasedCollection;true;firstT;();;Argument[this].Element;ReturnValue;value;tb-generated - public T firstT() { - return null; - } + // summary=p;TypeBasedCollection;true;firstT;();;Argument[this].Element;ReturnValue;value;tb-generated + public T firstT() { + return null; + } - // MaD=p;TypeBasedCollection;true;getManyT;();;Argument[this].Element;ReturnValue.Element;value;tb-generated - public List getManyT() { - return null; - } -} \ No newline at end of file + // summary=p;TypeBasedCollection;true;getManyT;();;Argument[this].Element;ReturnValue.Element;value;tb-generated + public List getManyT() { + return null; + } +} diff --git a/java/ql/test/utils/modelgenerator/typebasedflow/p/TypeBasedComplex.java b/java/ql/test/utils/modelgenerator/typebasedflow/p/TypeBasedComplex.java index ffca17457a0..a6e6c220475 100644 --- a/java/ql/test/utils/modelgenerator/typebasedflow/p/TypeBasedComplex.java +++ b/java/ql/test/utils/modelgenerator/typebasedflow/p/TypeBasedComplex.java @@ -5,87 +5,85 @@ import java.util.function.Function; public class TypeBasedComplex { - // MaD=p;TypeBasedComplex;true;addMany;(List);;Argument[0].Element;Argument[this].SyntheticField[ArgType0];value;tb-generated - public void addMany(List xs) { - } + // summary=p;TypeBasedComplex;true;addMany;(List);;Argument[0].Element;Argument[this].SyntheticField[ArgType0];value;tb-generated + public void addMany(List xs) {} - // MaD=p;TypeBasedComplex;true;getMany;();;Argument[this].SyntheticField[ArgType0];ReturnValue.Element;value;tb-generated - public List getMany() { - return null; - } + // summary=p;TypeBasedComplex;true;getMany;();;Argument[this].SyntheticField[ArgType0];ReturnValue.Element;value;tb-generated + public List getMany() { + return null; + } - // MaD=p;TypeBasedComplex;true;apply;(Function);;Argument[this].SyntheticField[ArgType0];Argument[0].Parameter[0];value;tb-generated - public Integer apply(Function f) { - return null; - } + // summary=p;TypeBasedComplex;true;apply;(Function);;Argument[this].SyntheticField[ArgType0];Argument[0].Parameter[0];value;tb-generated + public Integer apply(Function f) { + return null; + } - // A method that doesn't mention `T` in its type signature. - // This is for testing that we don't generate a summary that involves the - // implicit field for `T`. - // MaD=p;TypeBasedComplex;true;apply2;(Object,Function);;Argument[0];Argument[1].Parameter[0];value;tb-generated - // MaD=p;TypeBasedComplex;true;apply2;(Object,Function);;Argument[1].ReturnValue;ReturnValue;value;tb-generated - public T2 apply2(T1 x, Function f) { - return null; - } + // A method that doesn't mention `T` in its type signature. + // This is for testing that we don't generate a summary that involves the + // implicit field for `T`. + // summary=p;TypeBasedComplex;true;apply2;(Object,Function);;Argument[0];Argument[1].Parameter[0];value;tb-generated + // summary=p;TypeBasedComplex;true;apply2;(Object,Function);;Argument[1].ReturnValue;ReturnValue;value;tb-generated + public T2 apply2(T1 x, Function f) { + return null; + } - // MaD=p;TypeBasedComplex;true;flatMap;(Function);;Argument[this].SyntheticField[ArgType0];Argument[0].Parameter[0];value;tb-generated - // MaD=p;TypeBasedComplex;true;flatMap;(Function);;Argument[this].SyntheticField[ArgType0];ReturnValue.SyntheticField[ArgType0];value;tb-generated - // MaD=p;TypeBasedComplex;true;flatMap;(Function);;Argument[0].ReturnValue.Element;Argument[this].SyntheticField[ArgType0];value;tb-generated - // MaD=p;TypeBasedComplex;true;flatMap;(Function);;Argument[0].ReturnValue.Element;Argument[0].Parameter[0];value;tb-generated - // MaD=p;TypeBasedComplex;true;flatMap;(Function);;Argument[0].ReturnValue.Element;ReturnValue.SyntheticField[ArgType0];value;tb-generated - public TypeBasedComplex flatMap(Function> f) { - return null; - } + // summary=p;TypeBasedComplex;true;flatMap;(Function);;Argument[this].SyntheticField[ArgType0];Argument[0].Parameter[0];value;tb-generated + // summary=p;TypeBasedComplex;true;flatMap;(Function);;Argument[this].SyntheticField[ArgType0];ReturnValue.SyntheticField[ArgType0];value;tb-generated + // summary=p;TypeBasedComplex;true;flatMap;(Function);;Argument[0].ReturnValue.Element;Argument[this].SyntheticField[ArgType0];value;tb-generated + // summary=p;TypeBasedComplex;true;flatMap;(Function);;Argument[0].ReturnValue.Element;Argument[0].Parameter[0];value;tb-generated + // summary=p;TypeBasedComplex;true;flatMap;(Function);;Argument[0].ReturnValue.Element;ReturnValue.SyntheticField[ArgType0];value;tb-generated + public TypeBasedComplex flatMap(Function> f) { + return null; + } - // MaD=p;TypeBasedComplex;true;flatMap2;(Function);;Argument[this].SyntheticField[ArgType0];Argument[0].Parameter[0];value;tb-generated - // MaD=p;TypeBasedComplex;true;flatMap2;(Function);;Argument[0].ReturnValue.Element;ReturnValue.SyntheticField[ArgType0];value;tb-generated - public TypeBasedComplex flatMap2(Function> f) { - return null; - } + // summary=p;TypeBasedComplex;true;flatMap2;(Function);;Argument[this].SyntheticField[ArgType0];Argument[0].Parameter[0];value;tb-generated + // summary=p;TypeBasedComplex;true;flatMap2;(Function);;Argument[0].ReturnValue.Element;ReturnValue.SyntheticField[ArgType0];value;tb-generated + public TypeBasedComplex flatMap2(Function> f) { + return null; + } - // MaD=p;TypeBasedComplex;true;map;(Function);;Argument[this].SyntheticField[ArgType0];Argument[0].Parameter[0];value;tb-generated - // MaD=p;TypeBasedComplex;true;map;(Function);;Argument[0].ReturnValue;ReturnValue;value;tb-generated - public S map(Function f) { - return null; - } + // summary=p;TypeBasedComplex;true;map;(Function);;Argument[this].SyntheticField[ArgType0];Argument[0].Parameter[0];value;tb-generated + // summary=p;TypeBasedComplex;true;map;(Function);;Argument[0].ReturnValue;ReturnValue;value;tb-generated + public S map(Function f) { + return null; + } - // MaD=p;TypeBasedComplex;true;mapComplex;(Function);;Argument[this].SyntheticField[ArgType0];Argument[0].Parameter[0];value;tb-generated - // MaD=p;TypeBasedComplex;true;mapComplex;(Function);;Argument[0].ReturnValue;ReturnValue.SyntheticField[ArgType0];value;tb-generated - public TypeBasedComplex mapComplex(Function f) { - return null; - } + // summary=p;TypeBasedComplex;true;mapComplex;(Function);;Argument[this].SyntheticField[ArgType0];Argument[0].Parameter[0];value;tb-generated + // summary=p;TypeBasedComplex;true;mapComplex;(Function);;Argument[0].ReturnValue;ReturnValue.SyntheticField[ArgType0];value;tb-generated + public TypeBasedComplex mapComplex(Function f) { + return null; + } - // MaD=p;TypeBasedComplex;true;returnComplex;(Function);;Argument[this].SyntheticField[ArgType0];Argument[0].Parameter[0];value;tb-generated - // MaD=p;TypeBasedComplex;true;returnComplex;(Function);;Argument[this].SyntheticField[ArgType0];ReturnValue.SyntheticField[ArgType0];value;tb-generated - // MaD=p;TypeBasedComplex;true;returnComplex;(Function);;Argument[0].ReturnValue.SyntheticField[ArgType0];Argument[this].SyntheticField[ArgType0];value;tb-generated - // MaD=p;TypeBasedComplex;true;returnComplex;(Function);;Argument[0].ReturnValue.SyntheticField[ArgType0];Argument[0].Parameter[0];value;tb-generated - // MaD=p;TypeBasedComplex;true;returnComplex;(Function);;Argument[0].ReturnValue.SyntheticField[ArgType0];ReturnValue.SyntheticField[ArgType0];value;tb-generated - public TypeBasedComplex returnComplex(Function> f) { - return null; - } + // summary=p;TypeBasedComplex;true;returnComplex;(Function);;Argument[this].SyntheticField[ArgType0];Argument[0].Parameter[0];value;tb-generated + // summary=p;TypeBasedComplex;true;returnComplex;(Function);;Argument[this].SyntheticField[ArgType0];ReturnValue.SyntheticField[ArgType0];value;tb-generated + // summary=p;TypeBasedComplex;true;returnComplex;(Function);;Argument[0].ReturnValue.SyntheticField[ArgType0];Argument[this].SyntheticField[ArgType0];value;tb-generated + // summary=p;TypeBasedComplex;true;returnComplex;(Function);;Argument[0].ReturnValue.SyntheticField[ArgType0];Argument[0].Parameter[0];value;tb-generated + // summary=p;TypeBasedComplex;true;returnComplex;(Function);;Argument[0].ReturnValue.SyntheticField[ArgType0];ReturnValue.SyntheticField[ArgType0];value;tb-generated + public TypeBasedComplex returnComplex(Function> f) { + return null; + } - // MaD=p;TypeBasedComplex;true;set;(Integer,Function);;Argument[1].ReturnValue;Argument[this].SyntheticField[ArgType0];value;tb-generated - public void set(Integer x, Function f) { - } + // summary=p;TypeBasedComplex;true;set;(Integer,Function);;Argument[1].ReturnValue;Argument[this].SyntheticField[ArgType0];value;tb-generated + public void set(Integer x, Function f) {} - // MaD=p;TypeBasedComplex;true;applyMyFunction;(MyFunction,Integer);;Argument[this].SyntheticField[ArgType0];Argument[0].Parameter[0];value;tb-generated - // MaD=p;TypeBasedComplex;true;applyMyFunction;(MyFunction,Integer);;Argument[0].ReturnValue;Argument[this].SyntheticField[ArgType0];value;tb-generated - // MaD=p;TypeBasedComplex;true;applyMyFunction;(MyFunction,Integer);;Argument[0].ReturnValue;Argument[0].Parameter[0];value;tb-generated - public Integer applyMyFunction(MyFunction f, Integer x) { - return null; - } + // summary=p;TypeBasedComplex;true;applyMyFunction;(MyFunction,Integer);;Argument[this].SyntheticField[ArgType0];Argument[0].Parameter[0];value;tb-generated + // summary=p;TypeBasedComplex;true;applyMyFunction;(MyFunction,Integer);;Argument[0].ReturnValue;Argument[this].SyntheticField[ArgType0];value;tb-generated + // summary=p;TypeBasedComplex;true;applyMyFunction;(MyFunction,Integer);;Argument[0].ReturnValue;Argument[0].Parameter[0];value;tb-generated + public Integer applyMyFunction(MyFunction f, Integer x) { + return null; + } - // MaD=p;TypeBasedComplex;true;applyMyFunctionGeneric;(MyFunction,Object);;Argument[this].SyntheticField[ArgType0];Argument[0].Parameter[0];value;tb-generated - // MaD=p;TypeBasedComplex;true;applyMyFunctionGeneric;(MyFunction,Object);;Argument[0].ReturnValue;ReturnValue;value;tb-generated - // MaD=p;TypeBasedComplex;true;applyMyFunctionGeneric;(MyFunction,Object);;Argument[1];Argument[0].Parameter[1];value;tb-generated - public S2 applyMyFunctionGeneric(MyFunction f, S1 x) { - return null; - } + // summary=p;TypeBasedComplex;true;applyMyFunctionGeneric;(MyFunction,Object);;Argument[this].SyntheticField[ArgType0];Argument[0].Parameter[0];value;tb-generated + // summary=p;TypeBasedComplex;true;applyMyFunctionGeneric;(MyFunction,Object);;Argument[0].ReturnValue;ReturnValue;value;tb-generated + // summary=p;TypeBasedComplex;true;applyMyFunctionGeneric;(MyFunction,Object);;Argument[1];Argument[0].Parameter[1];value;tb-generated + public S2 applyMyFunctionGeneric(MyFunction f, S1 x) { + return null; + } - // MaD=p;TypeBasedComplex;true;applyMyFunctionGeneric;(MyFunction,Object,Object);;Argument[0].ReturnValue;ReturnValue;value;tb-generated - // MaD=p;TypeBasedComplex;true;applyMyFunctionGeneric;(MyFunction,Object,Object);;Argument[1];Argument[0].Parameter[0];value;tb-generated - // MaD=p;TypeBasedComplex;true;applyMyFunctionGeneric;(MyFunction,Object,Object);;Argument[2];Argument[0].Parameter[1];value;tb-generated - public S3 applyMyFunctionGeneric(MyFunction f, S1 x, S2 y) { - return null; - } -} \ No newline at end of file + // summary=p;TypeBasedComplex;true;applyMyFunctionGeneric;(MyFunction,Object,Object);;Argument[0].ReturnValue;ReturnValue;value;tb-generated + // summary=p;TypeBasedComplex;true;applyMyFunctionGeneric;(MyFunction,Object,Object);;Argument[1];Argument[0].Parameter[0];value;tb-generated + // summary=p;TypeBasedComplex;true;applyMyFunctionGeneric;(MyFunction,Object,Object);;Argument[2];Argument[0].Parameter[1];value;tb-generated + public S3 applyMyFunctionGeneric(MyFunction f, S1 x, S2 y) { + return null; + } +} diff --git a/java/ql/test/utils/modelgenerator/typebasedflow/p/TypeBasedSimple.java b/java/ql/test/utils/modelgenerator/typebasedflow/p/TypeBasedSimple.java index 8715bc2feeb..17b710922eb 100644 --- a/java/ql/test/utils/modelgenerator/typebasedflow/p/TypeBasedSimple.java +++ b/java/ql/test/utils/modelgenerator/typebasedflow/p/TypeBasedSimple.java @@ -2,41 +2,37 @@ package p; public class TypeBasedSimple { - // MaD=p;TypeBasedSimple;true;TypeBasedSimple;(Object);;Argument[0];Argument[this].SyntheticField[ArgType0];value;tb-generated - public TypeBasedSimple(T t) { - } + // summary=p;TypeBasedSimple;true;TypeBasedSimple;(Object);;Argument[0];Argument[this].SyntheticField[ArgType0];value;tb-generated + public TypeBasedSimple(T t) {} - // MaD=p;TypeBasedSimple;true;get;();;Argument[this].SyntheticField[ArgType0];ReturnValue;value;tb-generated - public T get() { - return null; - } + // summary=p;TypeBasedSimple;true;get;();;Argument[this].SyntheticField[ArgType0];ReturnValue;value;tb-generated + public T get() { + return null; + } - // MaD=p;TypeBasedSimple;true;get;(Object);;Argument[this].SyntheticField[ArgType0];ReturnValue;value;tb-generated - public T get(Object o) { - return null; - } + // summary=p;TypeBasedSimple;true;get;(Object);;Argument[this].SyntheticField[ArgType0];ReturnValue;value;tb-generated + public T get(Object o) { + return null; + } - // MaD=p;TypeBasedSimple;true;id;(Object);;Argument[this].SyntheticField[ArgType0];ReturnValue;value;tb-generated - // MaD=p;TypeBasedSimple;true;id;(Object);;Argument[0];Argument[this].SyntheticField[ArgType0];value;tb-generated - // MaD=p;TypeBasedSimple;true;id;(Object);;Argument[0];ReturnValue;value;tb-generated - public T id(T x) { - return null; - } + // summary=p;TypeBasedSimple;true;id;(Object);;Argument[this].SyntheticField[ArgType0];ReturnValue;value;tb-generated + // summary=p;TypeBasedSimple;true;id;(Object);;Argument[0];Argument[this].SyntheticField[ArgType0];value;tb-generated + // summary=p;TypeBasedSimple;true;id;(Object);;Argument[0];ReturnValue;value;tb-generated + public T id(T x) { + return null; + } - // MaD=p;TypeBasedSimple;true;id2;(Object);;Argument[0];ReturnValue;value;tb-generated - public S id2(S x) { - return null; - } + // summary=p;TypeBasedSimple;true;id2;(Object);;Argument[0];ReturnValue;value;tb-generated + public S id2(S x) { + return null; + } - // MaD=p;TypeBasedSimple;true;set;(Object);;Argument[0];Argument[this].SyntheticField[ArgType0];value;tb-generated - public void set(T x) { - } + // summary=p;TypeBasedSimple;true;set;(Object);;Argument[0];Argument[this].SyntheticField[ArgType0];value;tb-generated + public void set(T x) {} - // MaD=p;TypeBasedSimple;true;set;(int,Object);;Argument[1];Argument[this].SyntheticField[ArgType0];value;tb-generated - public void set(int x, T y) { - } + // summary=p;TypeBasedSimple;true;set;(int,Object);;Argument[1];Argument[this].SyntheticField[ArgType0];value;tb-generated + public void set(int x, T y) {} - // No summary as S is unrelated to T - public void set2(S x) { - } -} \ No newline at end of file + // No summary as S is unrelated to T + public void set2(S x) {} +} From 95ddd6ec743c8773ee94e5519ad8f97849c1491c Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 6 May 2024 13:34:03 +0200 Subject: [PATCH 6/9] Java: Generalize the inline mad test to allow further re-use. --- java/ql/test/TestUtilities/InlineMadTest.qll | 62 ++++++++++++------- .../dataflow/CaptureModels.expected | 4 +- .../modelgenerator/dataflow/CaptureModels.ql | 4 +- .../CaptureTypeBasedSummaryModels.expected | 4 +- .../CaptureTypeBasedSummaryModels.ql | 4 +- 5 files changed, 47 insertions(+), 31 deletions(-) diff --git a/java/ql/test/TestUtilities/InlineMadTest.qll b/java/ql/test/TestUtilities/InlineMadTest.qll index 3e9aee7eb9e..a5602036a8c 100644 --- a/java/ql/test/TestUtilities/InlineMadTest.qll +++ b/java/ql/test/TestUtilities/InlineMadTest.qll @@ -1,34 +1,50 @@ -signature module InlineMadTestConfigSig { +import java + +private signature module InlineMadTestLangSig { /** * Gets a relevant code comment, if any. */ string getComment(); +} + +signature module InlineMadTestConfigSig { + /** + * Gets the kind of the captured model. + */ + string getKind(); /** - * Gets an identified summary, if any. + * Gets a captured model, if any. */ - string getCapturedSummary(); + string getCapturedModel(); +} + +private module InlineMadTestImpl { + private string expects() { + Lang::getComment().regexpCapture(" *(SPURIOUS-)?" + Input::getKind() + "=(.*)", 2) = result + } + + query predicate unexpectedModel(string msg) { + exists(string flow | + flow = Input::getCapturedModel() and + not flow = expects() and + msg = "Unexpected " + Input::getKind() + " found: " + flow + ) + } + + query predicate expectedModel(string msg) { + exists(string e | + e = expects() and + not e = Input::getCapturedModel() and + msg = "Expected " + Input::getKind() + " missing: " + e + ) + } +} + +private module InlineMadTestLang implements InlineMadTestLangSig { + string getComment() { result = any(Javadoc doc).getChild(0).toString() } } module InlineMadTest { - bindingset[kind] - private string expects(string kind) { - Input::getComment().regexpCapture(" *(SPURIOUS-)?" + kind + "=(.*)", 2) = result - } - - query predicate unexpectedSummary(string msg) { - exists(string flow | - flow = Input::getCapturedSummary() and - not flow = expects("summary") and - msg = "Unexpected summary found: " + flow - ) - } - - query predicate expectedSummary(string msg) { - exists(string e | - e = expects("summary") and - not e = Input::getCapturedSummary() and - msg = "Expected summary missing: " + e - ) - } + import InlineMadTestImpl } diff --git a/java/ql/test/utils/modelgenerator/dataflow/CaptureModels.expected b/java/ql/test/utils/modelgenerator/dataflow/CaptureModels.expected index ee55a9c6ba6..cb6fc390349 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/CaptureModels.expected +++ b/java/ql/test/utils/modelgenerator/dataflow/CaptureModels.expected @@ -1,2 +1,2 @@ -unexpectedSummary -expectedSummary +unexpectedModel +expectedModel diff --git a/java/ql/test/utils/modelgenerator/dataflow/CaptureModels.ql b/java/ql/test/utils/modelgenerator/dataflow/CaptureModels.ql index 1a2dbd03d7a..821e8e8f0e7 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/CaptureModels.ql +++ b/java/ql/test/utils/modelgenerator/dataflow/CaptureModels.ql @@ -3,9 +3,9 @@ import utils.modelgenerator.internal.CaptureSummaryFlowQuery import TestUtilities.InlineMadTest module InlineMadTestConfig implements InlineMadTestConfigSig { - string getComment() { result = any(Javadoc doc).getChild(0).toString() } + string getCapturedModel() { result = captureFlow(_) } - string getCapturedSummary() { result = captureFlow(_) } + string getKind() { result = "summary" } } import InlineMadTest diff --git a/java/ql/test/utils/modelgenerator/typebasedflow/CaptureTypeBasedSummaryModels.expected b/java/ql/test/utils/modelgenerator/typebasedflow/CaptureTypeBasedSummaryModels.expected index ee55a9c6ba6..cb6fc390349 100644 --- a/java/ql/test/utils/modelgenerator/typebasedflow/CaptureTypeBasedSummaryModels.expected +++ b/java/ql/test/utils/modelgenerator/typebasedflow/CaptureTypeBasedSummaryModels.expected @@ -1,2 +1,2 @@ -unexpectedSummary -expectedSummary +unexpectedModel +expectedModel diff --git a/java/ql/test/utils/modelgenerator/typebasedflow/CaptureTypeBasedSummaryModels.ql b/java/ql/test/utils/modelgenerator/typebasedflow/CaptureTypeBasedSummaryModels.ql index c5c509ac326..e3b64cca785 100644 --- a/java/ql/test/utils/modelgenerator/typebasedflow/CaptureTypeBasedSummaryModels.ql +++ b/java/ql/test/utils/modelgenerator/typebasedflow/CaptureTypeBasedSummaryModels.ql @@ -3,9 +3,9 @@ import TestUtilities.InlineMadTest import utils.modelgenerator.internal.CaptureTypeBasedSummaryModels module InlineMadTestConfig implements InlineMadTestConfigSig { - string getComment() { result = any(Javadoc doc).getChild(0).toString() } + string getCapturedModel() { result = captureFlow(_) } - string getCapturedSummary() { result = captureFlow(_) } + string getKind() { result = "summary" } } import InlineMadTest From a8549d2e233938c043fdd9632f4d013ce8ec2165 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 6 May 2024 13:56:36 +0200 Subject: [PATCH 7/9] Java: Convert remaining tests to inline flow tests. --- .../dataflow/CaptureNeutralModels.expected | 27 +----------- .../dataflow/CaptureNeutralModels.ql | 11 +++++ .../dataflow/CaptureNeutralModels.qlref | 1 - .../dataflow/CaptureSinkModels.expected | 7 +-- .../dataflow/CaptureSinkModels.ql | 11 +++++ .../dataflow/CaptureSinkModels.qlref | 1 - .../dataflow/CaptureSourceModels.expected | 7 +-- .../dataflow/CaptureSourceModels.ql | 11 +++++ .../dataflow/CaptureSourceModels.qlref | 1 - ...expected => CaptureSummaryModels.expected} | 0 ...ptureModels.ql => CaptureSummaryModels.ql} | 0 .../modelgenerator/dataflow/p/Factory.java | 1 + .../modelgenerator/dataflow/p/FinalClass.java | 1 + .../modelgenerator/dataflow/p/FluentAPI.java | 1 + .../dataflow/p/ImmutablePojo.java | 1 + .../modelgenerator/dataflow/p/Joiner.java | 1 + .../modelgenerator/dataflow/p/ParamFlow.java | 2 + .../utils/modelgenerator/dataflow/p/Pojo.java | 9 ++++ .../p/PrivateFlowViaPublicInterface.java | 3 ++ .../modelgenerator/dataflow/p/Sinks.java | 41 ++++++++++------- .../modelgenerator/dataflow/p/Sources.java | 44 +++++++++++-------- 21 files changed, 108 insertions(+), 73 deletions(-) create mode 100644 java/ql/test/utils/modelgenerator/dataflow/CaptureNeutralModels.ql delete mode 100644 java/ql/test/utils/modelgenerator/dataflow/CaptureNeutralModels.qlref create mode 100644 java/ql/test/utils/modelgenerator/dataflow/CaptureSinkModels.ql delete mode 100644 java/ql/test/utils/modelgenerator/dataflow/CaptureSinkModels.qlref create mode 100644 java/ql/test/utils/modelgenerator/dataflow/CaptureSourceModels.ql delete mode 100644 java/ql/test/utils/modelgenerator/dataflow/CaptureSourceModels.qlref rename java/ql/test/utils/modelgenerator/dataflow/{CaptureModels.expected => CaptureSummaryModels.expected} (100%) rename java/ql/test/utils/modelgenerator/dataflow/{CaptureModels.ql => CaptureSummaryModels.ql} (100%) diff --git a/java/ql/test/utils/modelgenerator/dataflow/CaptureNeutralModels.expected b/java/ql/test/utils/modelgenerator/dataflow/CaptureNeutralModels.expected index df6a7bfc854..cb6fc390349 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/CaptureNeutralModels.expected +++ b/java/ql/test/utils/modelgenerator/dataflow/CaptureNeutralModels.expected @@ -1,25 +1,2 @@ -| p;Factory;getIntValue;();summary;df-generated | -| p;FinalClass;returnsConstant;();summary;df-generated | -| p;FluentAPI$Inner;notThis;(String);summary;df-generated | -| p;ImmutablePojo;getX;();summary;df-generated | -| p;Joiner;length;();summary;df-generated | -| p;ParamFlow;ignorePrimitiveReturnValue;(String);summary;df-generated | -| p;ParamFlow;mapType;(Class);summary;df-generated | -| p;Pojo;doNotSetValue;(String);summary;df-generated | -| p;Pojo;getBigDecimal;();summary;df-generated | -| p;Pojo;getBigInt;();summary;df-generated | -| p;Pojo;getBoxedArray;();summary;df-generated | -| p;Pojo;getBoxedCollection;();summary;df-generated | -| p;Pojo;getBoxedValue;();summary;df-generated | -| p;Pojo;getFloatArray;();summary;df-generated | -| p;Pojo;getIntValue;();summary;df-generated | -| p;Pojo;getPrimitiveArray;();summary;df-generated | -| p;PrivateFlowViaPublicInterface$SPI;openStreamNone;();summary;df-generated | -| p;PrivateFlowViaPublicInterface;createAnSPIWithoutTrackingFile;(File);summary;df-generated | -| p;Sinks;copyFileToDirectory;(Path,Path,CopyOption[]);summary;df-generated | -| p;Sinks;propagate;(String);summary;df-generated | -| p;Sinks;readUrl;(URL,Charset);summary;df-generated | -| p;Sources;readUrl;(URL);summary;df-generated | -| p;Sources;socketStream;();summary;df-generated | -| p;Sources;sourceToParameter;(InputStream[],List);summary;df-generated | -| p;Sources;wrappedSocketStream;();summary;df-generated | +unexpectedModel +expectedModel diff --git a/java/ql/test/utils/modelgenerator/dataflow/CaptureNeutralModels.ql b/java/ql/test/utils/modelgenerator/dataflow/CaptureNeutralModels.ql new file mode 100644 index 00000000000..50bc36fe4eb --- /dev/null +++ b/java/ql/test/utils/modelgenerator/dataflow/CaptureNeutralModels.ql @@ -0,0 +1,11 @@ +import java +import utils.modelgenerator.internal.CaptureSummaryFlowQuery +import TestUtilities.InlineMadTest + +module InlineMadTestConfig implements InlineMadTestConfigSig { + string getCapturedModel() { result = captureNoFlow(_) } + + string getKind() { result = "neutral" } +} + +import InlineMadTest diff --git a/java/ql/test/utils/modelgenerator/dataflow/CaptureNeutralModels.qlref b/java/ql/test/utils/modelgenerator/dataflow/CaptureNeutralModels.qlref deleted file mode 100644 index 851ddc0d294..00000000000 --- a/java/ql/test/utils/modelgenerator/dataflow/CaptureNeutralModels.qlref +++ /dev/null @@ -1 +0,0 @@ -utils/modelgenerator/CaptureNeutralModels.ql \ No newline at end of file diff --git a/java/ql/test/utils/modelgenerator/dataflow/CaptureSinkModels.expected b/java/ql/test/utils/modelgenerator/dataflow/CaptureSinkModels.expected index 799a1a37dd4..cb6fc390349 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/CaptureSinkModels.expected +++ b/java/ql/test/utils/modelgenerator/dataflow/CaptureSinkModels.expected @@ -1,5 +1,2 @@ -| p;PrivateFlowViaPublicInterface$SPI;true;openStream;();;Argument[this];path-injection;df-generated | -| p;Sinks;true;copyFileToDirectory;(Path,Path,CopyOption[]);;Argument[0];path-injection;df-generated | -| p;Sinks;true;copyFileToDirectory;(Path,Path,CopyOption[]);;Argument[1];path-injection;df-generated | -| p;Sinks;true;readUrl;(URL,Charset);;Argument[0];request-forgery;df-generated | -| p;Sources;true;readUrl;(URL);;Argument[0];request-forgery;df-generated | +unexpectedModel +expectedModel diff --git a/java/ql/test/utils/modelgenerator/dataflow/CaptureSinkModels.ql b/java/ql/test/utils/modelgenerator/dataflow/CaptureSinkModels.ql new file mode 100644 index 00000000000..2bf1c378f2a --- /dev/null +++ b/java/ql/test/utils/modelgenerator/dataflow/CaptureSinkModels.ql @@ -0,0 +1,11 @@ +import java +import utils.modelgenerator.internal.CaptureModels +import TestUtilities.InlineMadTest + +module InlineMadTestConfig implements InlineMadTestConfigSig { + string getCapturedModel() { result = captureSink(_) } + + string getKind() { result = "sink" } +} + +import InlineMadTest diff --git a/java/ql/test/utils/modelgenerator/dataflow/CaptureSinkModels.qlref b/java/ql/test/utils/modelgenerator/dataflow/CaptureSinkModels.qlref deleted file mode 100644 index 36d2f144247..00000000000 --- a/java/ql/test/utils/modelgenerator/dataflow/CaptureSinkModels.qlref +++ /dev/null @@ -1 +0,0 @@ -utils/modelgenerator/CaptureSinkModels.ql \ No newline at end of file diff --git a/java/ql/test/utils/modelgenerator/dataflow/CaptureSourceModels.expected b/java/ql/test/utils/modelgenerator/dataflow/CaptureSourceModels.expected index 0f8d0ff1f32..cb6fc390349 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/CaptureSourceModels.expected +++ b/java/ql/test/utils/modelgenerator/dataflow/CaptureSourceModels.expected @@ -1,5 +1,2 @@ -| p;Sources;true;readUrl;(URL);;ReturnValue;remote;df-generated | -| p;Sources;true;socketStream;();;ReturnValue;remote;df-generated | -| p;Sources;true;sourceToParameter;(InputStream[],List);;Argument[0].ArrayElement;remote;df-generated | -| p;Sources;true;sourceToParameter;(InputStream[],List);;Argument[1].Element;remote;df-generated | -| p;Sources;true;wrappedSocketStream;();;ReturnValue;remote;df-generated | +unexpectedModel +expectedModel diff --git a/java/ql/test/utils/modelgenerator/dataflow/CaptureSourceModels.ql b/java/ql/test/utils/modelgenerator/dataflow/CaptureSourceModels.ql new file mode 100644 index 00000000000..e628bd19eb4 --- /dev/null +++ b/java/ql/test/utils/modelgenerator/dataflow/CaptureSourceModels.ql @@ -0,0 +1,11 @@ +import java +import utils.modelgenerator.internal.CaptureModels +import TestUtilities.InlineMadTest + +module InlineMadTestConfig implements InlineMadTestConfigSig { + string getCapturedModel() { result = captureSource(_) } + + string getKind() { result = "source" } +} + +import InlineMadTest diff --git a/java/ql/test/utils/modelgenerator/dataflow/CaptureSourceModels.qlref b/java/ql/test/utils/modelgenerator/dataflow/CaptureSourceModels.qlref deleted file mode 100644 index 6bbb499fc27..00000000000 --- a/java/ql/test/utils/modelgenerator/dataflow/CaptureSourceModels.qlref +++ /dev/null @@ -1 +0,0 @@ -utils/modelgenerator/CaptureSourceModels.ql \ No newline at end of file diff --git a/java/ql/test/utils/modelgenerator/dataflow/CaptureModels.expected b/java/ql/test/utils/modelgenerator/dataflow/CaptureSummaryModels.expected similarity index 100% rename from java/ql/test/utils/modelgenerator/dataflow/CaptureModels.expected rename to java/ql/test/utils/modelgenerator/dataflow/CaptureSummaryModels.expected diff --git a/java/ql/test/utils/modelgenerator/dataflow/CaptureModels.ql b/java/ql/test/utils/modelgenerator/dataflow/CaptureSummaryModels.ql similarity index 100% rename from java/ql/test/utils/modelgenerator/dataflow/CaptureModels.ql rename to java/ql/test/utils/modelgenerator/dataflow/CaptureSummaryModels.ql diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/Factory.java b/java/ql/test/utils/modelgenerator/dataflow/p/Factory.java index 57d26429a93..1887e0ca73e 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/Factory.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/Factory.java @@ -26,6 +26,7 @@ public final class Factory { return value; } + // neutral=p;Factory;getIntValue;();summary;df-generated public int getIntValue() { return intValue; } diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/FinalClass.java b/java/ql/test/utils/modelgenerator/dataflow/p/FinalClass.java index 82a39533ce1..2638f818854 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/FinalClass.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/FinalClass.java @@ -9,6 +9,7 @@ public final class FinalClass { return input; } + // neutral=p;FinalClass;returnsConstant;();summary;df-generated public String returnsConstant() { return C; } diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/FluentAPI.java b/java/ql/test/utils/modelgenerator/dataflow/p/FluentAPI.java index 38fbb286bb0..b7793e30666 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/FluentAPI.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/FluentAPI.java @@ -8,6 +8,7 @@ public final class FluentAPI { } public class Inner { + // neutral=p;FluentAPI$Inner;notThis;(String);summary;df-generated public FluentAPI notThis(String input) { return FluentAPI.this; } diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/ImmutablePojo.java b/java/ql/test/utils/modelgenerator/dataflow/p/ImmutablePojo.java index 1b39856b445..0a2cf2d7dbd 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/ImmutablePojo.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/ImmutablePojo.java @@ -17,6 +17,7 @@ public final class ImmutablePojo { return value; } + // neutral=p;ImmutablePojo;getX;();summary;df-generated public long getX() { return x; } diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/Joiner.java b/java/ql/test/utils/modelgenerator/dataflow/p/Joiner.java index 60edb0fb71e..10fc72c907f 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/Joiner.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/Joiner.java @@ -117,6 +117,7 @@ public final class Joiner { } } + // neutral=p;Joiner;length;();summary;df-generated public int length() { return (size == 0 && emptyValue != null) ? emptyValue.length() diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/ParamFlow.java b/java/ql/test/utils/modelgenerator/dataflow/p/ParamFlow.java index 5c47e292a6b..d175ee9c71e 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/ParamFlow.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/ParamFlow.java @@ -12,6 +12,7 @@ public class ParamFlow { return input; } + // neutral=p;ParamFlow;ignorePrimitiveReturnValue;(String);summary;df-generated public int ignorePrimitiveReturnValue(String input) { return input.length(); } @@ -50,6 +51,7 @@ public class ParamFlow { return input.iterator().next(); } + // neutral=p;ParamFlow;mapType;(Class);summary;df-generated public Class mapType(Class input) { return input; } diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/Pojo.java b/java/ql/test/utils/modelgenerator/dataflow/p/Pojo.java index 524e448ef81..9d5de0517e1 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/Pojo.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/Pojo.java @@ -40,19 +40,23 @@ public final class Pojo { this.value = value; } + // neutral=p;Pojo;doNotSetValue;(String);summary;df-generated public int doNotSetValue(String value) { Holder h = new Holder(value); return h.length(); } + // neutral=p;Pojo;getIntValue;();summary;df-generated public int getIntValue() { return intValue; } + // neutral=p;Pojo;getBoxedValue;();summary;df-generated public Integer getBoxedValue() { return Integer.valueOf(intValue); } + // neutral=p;Pojo;getPrimitiveArray;();summary;df-generated public int[] getPrimitiveArray() { return new int[] {intValue}; } @@ -67,14 +71,17 @@ public final class Pojo { return byteArray; } + // neutral=p;Pojo;getFloatArray;();summary;df-generated public float[] getFloatArray() { return floatArray; } + // neutral=p;Pojo;getBoxedArray;();summary;df-generated public Integer[] getBoxedArray() { return new Integer[] {Integer.valueOf(intValue)}; } + // neutral=p;Pojo;getBoxedCollection;();summary;df-generated public Collection getBoxedCollection() { return List.of(Integer.valueOf(intValue)); } @@ -89,10 +96,12 @@ public final class Pojo { return byteObjectArray; } + // neutral=p;Pojo;getBigInt;();summary;df-generated public BigInteger getBigInt() { return BigInteger.valueOf(intValue); } + // neutral=p;Pojo;getBigDecimal;();summary;df-generated public BigDecimal getBigDecimal() { return new BigDecimal(value); } diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/PrivateFlowViaPublicInterface.java b/java/ql/test/utils/modelgenerator/dataflow/p/PrivateFlowViaPublicInterface.java index 6b5dbca3e11..75364887274 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/PrivateFlowViaPublicInterface.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/PrivateFlowViaPublicInterface.java @@ -13,8 +13,10 @@ public class PrivateFlowViaPublicInterface { public static interface SPI { // summary=p;PrivateFlowViaPublicInterface$SPI;true;openStream;();;Argument[this];ReturnValue;taint;df-generated + // sink=p;PrivateFlowViaPublicInterface$SPI;true;openStream;();;Argument[this];path-injection;df-generated OutputStream openStream() throws IOException; + // neutral=p;PrivateFlowViaPublicInterface$SPI;openStreamNone;();summary;df-generated default OutputStream openStreamNone() throws IOException { return null; } @@ -55,6 +57,7 @@ public class PrivateFlowViaPublicInterface { return new PrivateImplWithSink(file); } + // neutral=p;PrivateFlowViaPublicInterface;createAnSPIWithoutTrackingFile;(File);summary;df-generated public static SPI createAnSPIWithoutTrackingFile(File file) { return new PrivateImplWithRandomField(file); } diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/Sinks.java b/java/ql/test/utils/modelgenerator/dataflow/p/Sinks.java index 260f235920a..e9868b26073 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/Sinks.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/Sinks.java @@ -3,32 +3,39 @@ package p; import java.io.IOException; import java.io.InputStream; import java.net.URL; -import java.nio.file.CopyOption; import java.nio.charset.Charset; +import java.nio.file.CopyOption; import java.nio.file.Files; import java.nio.file.Path; import java.util.logging.Logger; public class Sinks { - - public Path copyFileToDirectory(final Path sourceFile, final Path targetFile, final CopyOption... copyOptions) throws IOException { - return Files.copy(sourceFile, targetFile, copyOptions); - } - public String readUrl(final URL url, Charset encoding) throws IOException { - try (InputStream in = url.openStream()) { - byte[] bytes = in.readAllBytes(); - return new String(bytes, encoding); - } - } + // sink=p;Sinks;true;copyFileToDirectory;(Path,Path,CopyOption[]);;Argument[0];path-injection;df-generated + // sink=p;Sinks;true;copyFileToDirectory;(Path,Path,CopyOption[]);;Argument[1];path-injection;df-generated + // neutral=p;Sinks;copyFileToDirectory;(Path,Path,CopyOption[]);summary;df-generated + public Path copyFileToDirectory( + final Path sourceFile, final Path targetFile, final CopyOption... copyOptions) + throws IOException { + return Files.copy(sourceFile, targetFile, copyOptions); + } - public static void main(String[] args) throws IOException { - String foo = new Sinks().readUrl(new URL(args[0]), Charset.defaultCharset()); + // sink=p;Sinks;true;readUrl;(URL,Charset);;Argument[0];request-forgery;df-generated + // neutral=p;Sinks;readUrl;(URL,Charset);summary;df-generated + public String readUrl(final URL url, Charset encoding) throws IOException { + try (InputStream in = url.openStream()) { + byte[] bytes = in.readAllBytes(); + return new String(bytes, encoding); } + } - public void propagate(String s) { - Logger logger = Logger.getLogger(Sinks.class.getSimpleName()); - logger.warning(s); - } + public static void main(String[] args) throws IOException { + String foo = new Sinks().readUrl(new URL(args[0]), Charset.defaultCharset()); + } + // neutral=p;Sinks;propagate;(String);summary;df-generated + public void propagate(String s) { + Logger logger = Logger.getLogger(Sinks.class.getSimpleName()); + logger.warning(s); + } } diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/Sources.java b/java/ql/test/utils/modelgenerator/dataflow/p/Sources.java index 7b008ff378f..436bf16797c 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/Sources.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/Sources.java @@ -4,29 +4,37 @@ import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.URL; -import java.util.function.Consumer; import java.util.List; - public class Sources { - - public InputStream readUrl(final URL url) throws IOException { - return url.openConnection().getInputStream(); - } - public InputStream socketStream() throws IOException { - ServerSocket socket = new ServerSocket(123); - return socket.accept().getInputStream(); - } + // source=p;Sources;true;readUrl;(URL);;ReturnValue;remote;df-generated + // sink=p;Sources;true;readUrl;(URL);;Argument[0];request-forgery;df-generated + // neutral=p;Sources;readUrl;(URL);summary;df-generated + public InputStream readUrl(final URL url) throws IOException { + return url.openConnection().getInputStream(); + } - public InputStream wrappedSocketStream() throws IOException { - return socketStream(); - } + // source=p;Sources;true;socketStream;();;ReturnValue;remote;df-generated + // neutral=p;Sources;socketStream;();summary;df-generated + public InputStream socketStream() throws IOException { + ServerSocket socket = new ServerSocket(123); + return socket.accept().getInputStream(); + } - public void sourceToParameter(InputStream[] streams, List otherStreams) throws IOException { - ServerSocket socket = new ServerSocket(123); - streams[0] = socket.accept().getInputStream(); - otherStreams.add(socket.accept().getInputStream()); - } + // source=p;Sources;true;wrappedSocketStream;();;ReturnValue;remote;df-generated + // neutral=p;Sources;wrappedSocketStream;();summary;df-generated + public InputStream wrappedSocketStream() throws IOException { + return socketStream(); + } + // source=p;Sources;true;sourceToParameter;(InputStream[],List);;Argument[0].ArrayElement;remote;df-generated + // source=p;Sources;true;sourceToParameter;(InputStream[],List);;Argument[1].Element;remote;df-generated + // neutral=p;Sources;sourceToParameter;(InputStream[],List);summary;df-generated + public void sourceToParameter(InputStream[] streams, List otherStreams) + throws IOException { + ServerSocket socket = new ServerSocket(123); + streams[0] = socket.accept().getInputStream(); + otherStreams.add(socket.accept().getInputStream()); + } } From b53fa0f7f36db827d831fe13c0628e856d179f44 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 6 May 2024 16:32:28 +0200 Subject: [PATCH 8/9] Java: Ensure that it is the callable for the model origin that carries the comment containing the model. --- java/ql/test/TestUtilities/InlineMadTest.qll | 34 +++++++++++-------- .../dataflow/CaptureNeutralModels.ql | 2 +- .../dataflow/CaptureSinkModels.ql | 2 +- .../dataflow/CaptureSourceModels.ql | 2 +- .../dataflow/CaptureSummaryModels.ql | 2 +- .../dataflow/p/MultipleImpl2.java | 2 +- .../dataflow/p/MultipleImpls.java | 4 +-- .../p/PrivateFlowViaPublicInterface.java | 6 ++-- .../CaptureTypeBasedSummaryModels.ql | 2 +- 9 files changed, 31 insertions(+), 25 deletions(-) diff --git a/java/ql/test/TestUtilities/InlineMadTest.qll b/java/ql/test/TestUtilities/InlineMadTest.qll index a5602036a8c..31206a6338c 100644 --- a/java/ql/test/TestUtilities/InlineMadTest.qll +++ b/java/ql/test/TestUtilities/InlineMadTest.qll @@ -2,47 +2,53 @@ import java private signature module InlineMadTestLangSig { /** - * Gets a relevant code comment, if any. + * Gets a relevant code comment for `c`, if any. */ - string getComment(); + string getComment(Callable c); } signature module InlineMadTestConfigSig { /** - * Gets the kind of the captured model. + * Gets the kind of a captured model. */ string getKind(); /** - * Gets a captured model, if any. + * Gets a captured model for `c`, if any. */ - string getCapturedModel(); + string getCapturedModel(Callable c); } private module InlineMadTestImpl { - private string expects() { - Lang::getComment().regexpCapture(" *(SPURIOUS-)?" + Input::getKind() + "=(.*)", 2) = result + private string expects(Callable c) { + Lang::getComment(c).regexpCapture(" *(SPURIOUS-)?" + Input::getKind() + "=(.*)", 2) = result } query predicate unexpectedModel(string msg) { - exists(string flow | - flow = Input::getCapturedModel() and - not flow = expects() and + exists(Callable c, string flow | + flow = Input::getCapturedModel(c) and + not flow = expects(c) and msg = "Unexpected " + Input::getKind() + " found: " + flow ) } query predicate expectedModel(string msg) { - exists(string e | - e = expects() and - not e = Input::getCapturedModel() and + exists(Callable c, string e | + e = expects(c) and + not e = Input::getCapturedModel(c) and msg = "Expected " + Input::getKind() + " missing: " + e ) } } private module InlineMadTestLang implements InlineMadTestLangSig { - string getComment() { result = any(Javadoc doc).getChild(0).toString() } + string getComment(Callable c) { + exists(Javadoc doc | + hasJavadoc(c, doc) and + isNormalComment(doc) and + result = doc.getChild(0).toString() + ) + } } module InlineMadTest { diff --git a/java/ql/test/utils/modelgenerator/dataflow/CaptureNeutralModels.ql b/java/ql/test/utils/modelgenerator/dataflow/CaptureNeutralModels.ql index 50bc36fe4eb..e68730cc0ed 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/CaptureNeutralModels.ql +++ b/java/ql/test/utils/modelgenerator/dataflow/CaptureNeutralModels.ql @@ -3,7 +3,7 @@ import utils.modelgenerator.internal.CaptureSummaryFlowQuery import TestUtilities.InlineMadTest module InlineMadTestConfig implements InlineMadTestConfigSig { - string getCapturedModel() { result = captureNoFlow(_) } + string getCapturedModel(Callable c) { result = captureNoFlow(c) } string getKind() { result = "neutral" } } diff --git a/java/ql/test/utils/modelgenerator/dataflow/CaptureSinkModels.ql b/java/ql/test/utils/modelgenerator/dataflow/CaptureSinkModels.ql index 2bf1c378f2a..1acde2ade49 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/CaptureSinkModels.ql +++ b/java/ql/test/utils/modelgenerator/dataflow/CaptureSinkModels.ql @@ -3,7 +3,7 @@ import utils.modelgenerator.internal.CaptureModels import TestUtilities.InlineMadTest module InlineMadTestConfig implements InlineMadTestConfigSig { - string getCapturedModel() { result = captureSink(_) } + string getCapturedModel(Callable c) { result = captureSink(c) } string getKind() { result = "sink" } } diff --git a/java/ql/test/utils/modelgenerator/dataflow/CaptureSourceModels.ql b/java/ql/test/utils/modelgenerator/dataflow/CaptureSourceModels.ql index e628bd19eb4..7596f4f8cc1 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/CaptureSourceModels.ql +++ b/java/ql/test/utils/modelgenerator/dataflow/CaptureSourceModels.ql @@ -3,7 +3,7 @@ import utils.modelgenerator.internal.CaptureModels import TestUtilities.InlineMadTest module InlineMadTestConfig implements InlineMadTestConfigSig { - string getCapturedModel() { result = captureSource(_) } + string getCapturedModel(Callable c) { result = captureSource(c) } string getKind() { result = "source" } } diff --git a/java/ql/test/utils/modelgenerator/dataflow/CaptureSummaryModels.ql b/java/ql/test/utils/modelgenerator/dataflow/CaptureSummaryModels.ql index 821e8e8f0e7..415ebab1343 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/CaptureSummaryModels.ql +++ b/java/ql/test/utils/modelgenerator/dataflow/CaptureSummaryModels.ql @@ -3,7 +3,7 @@ import utils.modelgenerator.internal.CaptureSummaryFlowQuery import TestUtilities.InlineMadTest module InlineMadTestConfig implements InlineMadTestConfigSig { - string getCapturedModel() { result = captureFlow(_) } + string getCapturedModel(Callable c) { result = captureFlow(c) } string getKind() { result = "summary" } } diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/MultipleImpl2.java b/java/ql/test/utils/modelgenerator/dataflow/p/MultipleImpl2.java index dc67d0dfe6c..3e5d9abd768 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/MultipleImpl2.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/MultipleImpl2.java @@ -6,7 +6,6 @@ class MultipleImpl2 { // This is used to test that we only generate a summary model and // not neutral summary model for `IInterface.m`. public interface IInterface { - // summary=p;MultipleImpl2$IInterface;true;m;(Object);;Argument[0];ReturnValue;taint;df-generated Object m(Object value); } @@ -17,6 +16,7 @@ class MultipleImpl2 { } public class Impl2 implements IInterface { + // summary=p;MultipleImpl2$IInterface;true;m;(Object);;Argument[0];ReturnValue;taint;df-generated public Object m(Object value) { return value; } diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/MultipleImpls.java b/java/ql/test/utils/modelgenerator/dataflow/p/MultipleImpls.java index 8fccdf76ab7..d2b4ac133b5 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/MultipleImpls.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/MultipleImpls.java @@ -5,12 +5,11 @@ import java.util.concurrent.Callable; public class MultipleImpls { public static interface Strategy { - // summary=p;MultipleImpls$Strategy;true;doSomething;(String);;Argument[0];Argument[this];taint;df-generated - // summary=p;MultipleImpls$Strategy;true;doSomething;(String);;Argument[0];ReturnValue;taint;df-generated String doSomething(String value); } public static class Strat1 implements Strategy { + // summary=p;MultipleImpls$Strategy;true;doSomething;(String);;Argument[0];ReturnValue;taint;df-generated public String doSomething(String value) { return value; } @@ -28,6 +27,7 @@ public class MultipleImpls { public static class Strat2 implements Strategy { private String foo; + // summary=p;MultipleImpls$Strategy;true;doSomething;(String);;Argument[0];Argument[this];taint;df-generated public String doSomething(String value) { this.foo = value; return "none"; diff --git a/java/ql/test/utils/modelgenerator/dataflow/p/PrivateFlowViaPublicInterface.java b/java/ql/test/utils/modelgenerator/dataflow/p/PrivateFlowViaPublicInterface.java index 75364887274..25c62172121 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/p/PrivateFlowViaPublicInterface.java +++ b/java/ql/test/utils/modelgenerator/dataflow/p/PrivateFlowViaPublicInterface.java @@ -12,15 +12,12 @@ public class PrivateFlowViaPublicInterface { } public static interface SPI { - // summary=p;PrivateFlowViaPublicInterface$SPI;true;openStream;();;Argument[this];ReturnValue;taint;df-generated - // sink=p;PrivateFlowViaPublicInterface$SPI;true;openStream;();;Argument[this];path-injection;df-generated OutputStream openStream() throws IOException; // neutral=p;PrivateFlowViaPublicInterface$SPI;openStreamNone;();summary;df-generated default OutputStream openStreamNone() throws IOException { return null; } - ; } private static final class PrivateImplWithSink implements SPI { @@ -31,6 +28,8 @@ public class PrivateFlowViaPublicInterface { this.file = file; } + // summary=p;PrivateFlowViaPublicInterface$SPI;true;openStream;();;Argument[this];ReturnValue;taint;df-generated + // sink=p;PrivateFlowViaPublicInterface$SPI;true;openStream;();;Argument[this];path-injection;df-generated @Override public OutputStream openStream() throws IOException { return new FileOutputStream(file); @@ -46,6 +45,7 @@ public class PrivateFlowViaPublicInterface { return null; } + // neutral=p;PrivateFlowViaPublicInterface$SPI;openStreamNone;();summary;df-generated @Override public OutputStream openStreamNone() throws IOException { return new FileOutputStream(new RandomPojo().someFile); diff --git a/java/ql/test/utils/modelgenerator/typebasedflow/CaptureTypeBasedSummaryModels.ql b/java/ql/test/utils/modelgenerator/typebasedflow/CaptureTypeBasedSummaryModels.ql index e3b64cca785..2bf4e08d2c1 100644 --- a/java/ql/test/utils/modelgenerator/typebasedflow/CaptureTypeBasedSummaryModels.ql +++ b/java/ql/test/utils/modelgenerator/typebasedflow/CaptureTypeBasedSummaryModels.ql @@ -3,7 +3,7 @@ import TestUtilities.InlineMadTest import utils.modelgenerator.internal.CaptureTypeBasedSummaryModels module InlineMadTestConfig implements InlineMadTestConfigSig { - string getCapturedModel() { result = captureFlow(_) } + string getCapturedModel(Callable c) { result = captureFlow(c) } string getKind() { result = "summary" } } From 5fe3ab789095d4033204574dd31348240f63ea45 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Tue, 7 May 2024 10:12:15 +0200 Subject: [PATCH 9/9] Java: Prepare for inline test sharing with C#. --- java/ql/test/TestUtilities/InlineMadTest.qll | 71 +++++++++++--------- 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/java/ql/test/TestUtilities/InlineMadTest.qll b/java/ql/test/TestUtilities/InlineMadTest.qll index 31206a6338c..a336fa6b3a9 100644 --- a/java/ql/test/TestUtilities/InlineMadTest.qll +++ b/java/ql/test/TestUtilities/InlineMadTest.qll @@ -1,49 +1,60 @@ -import java +import java as J private signature module InlineMadTestLangSig { + /** + * A base class of callables for modeling. + */ + class Callable; + /** * Gets a relevant code comment for `c`, if any. */ string getComment(Callable c); } -signature module InlineMadTestConfigSig { - /** - * Gets the kind of a captured model. - */ - string getKind(); +private module InlineMadTestImpl { + private class Callable = Lang::Callable; - /** - * Gets a captured model for `c`, if any. - */ - string getCapturedModel(Callable c); -} + signature module InlineMadTestConfigSig { + /** + * Gets the kind of a captured model. + */ + string getKind(); -private module InlineMadTestImpl { - private string expects(Callable c) { - Lang::getComment(c).regexpCapture(" *(SPURIOUS-)?" + Input::getKind() + "=(.*)", 2) = result + /** + * Gets a captured model for `c`, if any. + */ + string getCapturedModel(Callable c); } - query predicate unexpectedModel(string msg) { - exists(Callable c, string flow | - flow = Input::getCapturedModel(c) and - not flow = expects(c) and - msg = "Unexpected " + Input::getKind() + " found: " + flow - ) - } + module InlineMadTest { + private string expects(Callable c) { + Lang::getComment(c).regexpCapture(" *(SPURIOUS-)?" + Input::getKind() + "=(.*)", 2) = result + } - query predicate expectedModel(string msg) { - exists(Callable c, string e | - e = expects(c) and - not e = Input::getCapturedModel(c) and - msg = "Expected " + Input::getKind() + " missing: " + e - ) + query predicate unexpectedModel(string msg) { + exists(Callable c, string flow | + flow = Input::getCapturedModel(c) and + not flow = expects(c) and + msg = "Unexpected " + Input::getKind() + " found: " + flow + ) + } + + query predicate expectedModel(string msg) { + exists(Callable c, string e | + e = expects(c) and + not e = Input::getCapturedModel(c) and + msg = "Expected " + Input::getKind() + " missing: " + e + ) + } } } private module InlineMadTestLang implements InlineMadTestLangSig { + class Callable = J::Callable; + string getComment(Callable c) { - exists(Javadoc doc | + exists(J::Javadoc doc | hasJavadoc(c, doc) and isNormalComment(doc) and result = doc.getChild(0).toString() @@ -51,6 +62,4 @@ private module InlineMadTestLang implements InlineMadTestLangSig { } } -module InlineMadTest { - import InlineMadTestImpl -} +import InlineMadTestImpl