mirror of
https://github.com/github/codeql.git
synced 2026-04-25 16:55:19 +02:00
Merge pull request #17521 from michaelnebel/modelgen/moreimprovements
C#/Java: Content based model generation improvements.
This commit is contained in:
@@ -9,5 +9,5 @@
|
||||
import internal.CaptureModels
|
||||
|
||||
from DataFlowSummaryTargetApi api, string flow
|
||||
where flow = ContentSensitive::captureFlow(api)
|
||||
where flow = ContentSensitive::captureFlow(api, _)
|
||||
select flow order by flow
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* @name Capture mixed neutral models.
|
||||
* @description Finds neutral models to be used by other queries.
|
||||
* @kind diagnostic
|
||||
* @id java/utils/modelgenerator/mixed-neutral-models
|
||||
* @tags modelgenerator
|
||||
*/
|
||||
|
||||
import internal.CaptureModels
|
||||
|
||||
from DataFlowSummaryTargetApi api, string noflow
|
||||
where noflow = captureMixedNeutral(api)
|
||||
select noflow order by noflow
|
||||
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* @name Capture mixed summary models.
|
||||
* @description Finds applicable summary models to be used by other queries.
|
||||
* @kind diagnostic
|
||||
* @id java/utils/modelgenerator/mixed-summary-models
|
||||
* @tags modelgenerator
|
||||
*/
|
||||
|
||||
import internal.CaptureModels
|
||||
|
||||
from DataFlowSummaryTargetApi api, string flow
|
||||
where flow = captureMixedFlow(api, _)
|
||||
select flow order by flow
|
||||
@@ -110,7 +110,10 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, JavaDataF
|
||||
|
||||
Callable lift() { result = lift }
|
||||
|
||||
predicate isRelevant() { relevant(this) }
|
||||
predicate isRelevant() {
|
||||
relevant(this) and
|
||||
not hasManualSummaryModel(this)
|
||||
}
|
||||
}
|
||||
|
||||
private string isExtensible(Callable c) {
|
||||
|
||||
@@ -54,6 +54,8 @@ public class C {
|
||||
// The summary for the parameter is ignored, because it is generated and
|
||||
// because there is a manual neutral summary model for this callable.
|
||||
lib.apiStepArgQualGeneratedIgnored(arg1);
|
||||
|
||||
lib.getValue();
|
||||
}
|
||||
|
||||
void fooPossibleLibraryDispatch(Library lib) {
|
||||
|
||||
@@ -11,4 +11,5 @@ invalidModelRow
|
||||
| C.java:44:32:44:35 | arg1 | C.java:44:5:44:36 | apiStepArgResGenerated(...) |
|
||||
| C.java:50:45:50:48 | arg2 | C.java:50:5:50:49 | apiStepArgResGeneratedIgnored(...) |
|
||||
| C.java:52:33:52:36 | arg1 | C.java:52:5:52:7 | lib [post update] |
|
||||
| C.java:62:12:62:15 | arg1 | C.java:62:5:62:16 | id(...) |
|
||||
| C.java:58:5:58:7 | lib | C.java:58:5:58:18 | getValue(...) |
|
||||
| C.java:64:12:64:15 | arg1 | C.java:64:5:64:16 | id(...) |
|
||||
|
||||
@@ -16,6 +16,7 @@ extensions:
|
||||
- ["my.qltest.external", "Library", False, "apiStepArgQualGenerated", "(Object)", "", "Argument[0]", "Argument[this]", "taint", "df-generated"]
|
||||
- ["my.qltest.external", "Library", False, "apiStepArgQualGeneratedIgnored", "(Object)", "", "Argument[0]", "Argument[this]", "taint", "df-generated"]
|
||||
- ["my.qltest.external", "Library", False, "id", "(Object)", "", "Argument[0]", "ReturnValue", "taint", "df-generated"]
|
||||
- ["my.qltest.external", "Library", False, "getValue", "()", "", "Argument[this]", "ReturnValue", "taint", "dfc-generated"]
|
||||
- addsTo:
|
||||
pack: codeql/java-all
|
||||
extensible: neutralModel
|
||||
|
||||
@@ -20,4 +20,8 @@ public class Library {
|
||||
public Object id(Object x) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import utils.modelgenerator.internal.CaptureModels
|
||||
import TestUtilities.InlineMadTest
|
||||
|
||||
module InlineMadTestConfig implements InlineMadTestConfigSig {
|
||||
string getCapturedModel(Callable c) { result = ContentSensitive::captureFlow(c) }
|
||||
string getCapturedModel(Callable c) { result = ContentSensitive::captureFlow(c, _) }
|
||||
|
||||
string getKind() { result = "contentbased-summary" }
|
||||
}
|
||||
|
||||
@@ -7,13 +7,13 @@ public final class Factory {
|
||||
private int intValue;
|
||||
|
||||
// summary=p;Factory;false;create;(String,int);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Factory;false;create;(String,int);;Argument[0];ReturnValue.Field[p.Factory.value];value;df-generated
|
||||
// contentbased-summary=p;Factory;false;create;(String,int);;Argument[0];ReturnValue.Field[p.Factory.value];value;dfc-generated
|
||||
public static Factory create(String value, int foo) {
|
||||
return new Factory(value, foo);
|
||||
}
|
||||
|
||||
// summary=p;Factory;false;create;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Factory;false;create;(String);;Argument[0];ReturnValue.Field[p.Factory.value];value;df-generated
|
||||
// contentbased-summary=p;Factory;false;create;(String);;Argument[0];ReturnValue.Field[p.Factory.value];value;dfc-generated
|
||||
public static Factory create(String value) {
|
||||
return new Factory(value, 0);
|
||||
}
|
||||
@@ -24,7 +24,7 @@ public final class Factory {
|
||||
}
|
||||
|
||||
// summary=p;Factory;false;getValue;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Factory;false;getValue;();;Argument[this].Field[p.Factory.value];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;Factory;false;getValue;();;Argument[this].Field[p.Factory.value];ReturnValue;value;dfc-generated
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
68
java/ql/test/utils/modelgenerator/dataflow/p/Fanout.java
Normal file
68
java/ql/test/utils/modelgenerator/dataflow/p/Fanout.java
Normal file
@@ -0,0 +1,68 @@
|
||||
package p;
|
||||
|
||||
public class Fanout {
|
||||
public interface I1 {
|
||||
String getValue();
|
||||
}
|
||||
|
||||
public interface I2 extends I1 {}
|
||||
|
||||
public class Impl1 implements I1 {
|
||||
public String v;
|
||||
|
||||
// summary=p;Fanout$I1;true;getValue;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Fanout$Impl1;true;getValue;();;Argument[this].Field[p.Fanout$Impl1.v];ReturnValue;value;dfc-generated
|
||||
public String getValue() {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
public class Impl2 implements I2 {
|
||||
public String v;
|
||||
|
||||
// summary=p;Fanout$I1;true;getValue;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Fanout$Impl2;true;getValue;();;Argument[this].Field[p.Fanout$Impl2.v];ReturnValue;value;dfc-generated
|
||||
public String getValue() {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
public class Impl3 implements I2 {
|
||||
public String v;
|
||||
|
||||
// summary=p;Fanout$I1;true;getValue;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Fanout$Impl3;true;getValue;();;Argument[this].Field[p.Fanout$Impl3.v];ReturnValue;value;dfc-generated
|
||||
public String getValue() {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
public class Impl4 implements I2 {
|
||||
public String v;
|
||||
|
||||
// summary=p;Fanout$I1;true;getValue;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Fanout$Impl4;true;getValue;();;Argument[this].Field[p.Fanout$Impl4.v];ReturnValue;value;dfc-generated
|
||||
public String getValue() {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
// summary=p;Fanout;true;concatGetValueOnI1;(String,Fanout$I1);;Argument[0];ReturnValue;taint;df-generated
|
||||
// summary=p;Fanout;true;concatGetValueOnI1;(String,Fanout$I1);;Argument[1];ReturnValue;taint;df-generated
|
||||
// No content based summaries are expected for this method on parameter `i`
|
||||
// as the fanout (number of content flows) exceeds the limit of 3.
|
||||
// contentbased-summary=p;Fanout;true;concatGetValueOnI1;(String,Fanout$I1);;Argument[0];ReturnValue;taint;dfc-generated
|
||||
public String concatGetValueOnI1(String other, I1 i) {
|
||||
return other + i.getValue();
|
||||
}
|
||||
|
||||
// summary=p;Fanout;true;concatGetValueOnI2;(String,Fanout$I2);;Argument[0];ReturnValue;taint;df-generated
|
||||
// summary=p;Fanout;true;concatGetValueOnI2;(String,Fanout$I2);;Argument[1];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Fanout;true;concatGetValueOnI2;(String,Fanout$I2);;Argument[0];ReturnValue;taint;dfc-generated
|
||||
// contentbased-summary=p;Fanout;true;concatGetValueOnI2;(String,Fanout$I2);;Argument[1].Field[p.Fanout$Impl2.v];ReturnValue;taint;dfc-generated
|
||||
// contentbased-summary=p;Fanout;true;concatGetValueOnI2;(String,Fanout$I2);;Argument[1].Field[p.Fanout$Impl3.v];ReturnValue;taint;dfc-generated
|
||||
// contentbased-summary=p;Fanout;true;concatGetValueOnI2;(String,Fanout$I2);;Argument[1].Field[p.Fanout$Impl4.v];ReturnValue;taint;dfc-generated
|
||||
public String concatGetValueOnI2(String other, I2 i) {
|
||||
return other + i.getValue();
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ public final class FinalClass {
|
||||
private static final String C = "constant";
|
||||
|
||||
// summary=p;FinalClass;false;returnsInput;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;FinalClass;false;returnsInput;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;FinalClass;false;returnsInput;(String);;Argument[0];ReturnValue;value;dfc-generated
|
||||
public String returnsInput(String input) {
|
||||
return input;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package p;
|
||||
public final class FluentAPI {
|
||||
|
||||
// summary=p;FluentAPI;false;returnsThis;(String);;Argument[this];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;FluentAPI;false;returnsThis;(String);;Argument[this];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;FluentAPI;false;returnsThis;(String);;Argument[this];ReturnValue;value;dfc-generated
|
||||
public FluentAPI returnsThis(String input) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -7,14 +7,14 @@ public final class ImmutablePojo {
|
||||
private final long x;
|
||||
|
||||
// summary=p;ImmutablePojo;false;ImmutablePojo;(String,int);;Argument[0];Argument[this];taint;df-generated
|
||||
// contentbased-summary=p;ImmutablePojo;false;ImmutablePojo;(String,int);;Argument[0];Argument[this].SyntheticField[p.ImmutablePojo.value];value;df-generated
|
||||
// contentbased-summary=p;ImmutablePojo;false;ImmutablePojo;(String,int);;Argument[0];Argument[this].SyntheticField[p.ImmutablePojo.value];value;dfc-generated
|
||||
public ImmutablePojo(String value, int x) {
|
||||
this.value = value;
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
// summary=p;ImmutablePojo;false;getValue;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;ImmutablePojo;false;getValue;();;Argument[this].SyntheticField[p.ImmutablePojo.value];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;ImmutablePojo;false;getValue;();;Argument[this].SyntheticField[p.ImmutablePojo.value];ReturnValue;value;dfc-generated
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
@@ -26,8 +26,8 @@ public final class ImmutablePojo {
|
||||
|
||||
// summary=p;ImmutablePojo;false;or;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// summary=p;ImmutablePojo;false;or;(String);;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;ImmutablePojo;false;or;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;ImmutablePojo;false;or;(String);;Argument[this].SyntheticField[p.ImmutablePojo.value];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;ImmutablePojo;false;or;(String);;Argument[0];ReturnValue;value;dfc-generated
|
||||
// contentbased-summary=p;ImmutablePojo;false;or;(String);;Argument[this].SyntheticField[p.ImmutablePojo.value];ReturnValue;value;dfc-generated
|
||||
public String or(String defaultValue) {
|
||||
return value != null ? value : defaultValue;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ public class Inheritance {
|
||||
|
||||
public class AImplBasePrivateImpl extends BasePrivate {
|
||||
// summary=p;Inheritance$AImplBasePrivateImpl;true;id;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Inheritance$AImplBasePrivateImpl;true;id;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;Inheritance$AImplBasePrivateImpl;true;id;(String);;Argument[0];ReturnValue;value;dfc-generated
|
||||
@Override
|
||||
public String id(String s) {
|
||||
return s;
|
||||
@@ -20,7 +20,7 @@ public class Inheritance {
|
||||
|
||||
public class AImplBasePublic extends BasePublic {
|
||||
// summary=p;Inheritance$BasePublic;true;id;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Inheritance$BasePublic;true;id;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;Inheritance$BasePublic;true;id;(String);;Argument[0];ReturnValue;value;dfc-generated
|
||||
@Override
|
||||
public String id(String s) {
|
||||
return s;
|
||||
@@ -61,7 +61,7 @@ public class Inheritance {
|
||||
|
||||
public class BImpl extends B {
|
||||
// summary=p;Inheritance$IPublic1;true;id;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Inheritance$IPublic1;true;id;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;Inheritance$IPublic1;true;id;(String);;Argument[0];ReturnValue;value;dfc-generated
|
||||
@Override
|
||||
public String id(String s) {
|
||||
return s;
|
||||
@@ -70,7 +70,7 @@ public class Inheritance {
|
||||
|
||||
public class CImpl extends C {
|
||||
// summary=p;Inheritance$C;true;id;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Inheritance$C;true;id;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;Inheritance$C;true;id;(String);;Argument[0];ReturnValue;value;dfc-generated
|
||||
@Override
|
||||
public String id(String s) {
|
||||
return s;
|
||||
@@ -79,7 +79,7 @@ public class Inheritance {
|
||||
|
||||
public class DImpl extends D {
|
||||
// summary=p;Inheritance$IPublic2;true;id;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Inheritance$IPublic2;true;id;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;Inheritance$IPublic2;true;id;(String);;Argument[0];ReturnValue;value;dfc-generated
|
||||
@Override
|
||||
public String id(String s) {
|
||||
return s;
|
||||
@@ -88,7 +88,7 @@ public class Inheritance {
|
||||
|
||||
public class EImpl extends E {
|
||||
// summary=p;Inheritance$EImpl;true;id;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Inheritance$EImpl;true;id;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;Inheritance$EImpl;true;id;(String);;Argument[0];ReturnValue;value;dfc-generated
|
||||
@Override
|
||||
public String id(String s) {
|
||||
return s;
|
||||
|
||||
@@ -10,14 +10,14 @@ public class InnerClasses {
|
||||
|
||||
public class CaptureMe {
|
||||
// summary=p;InnerClasses$CaptureMe;true;yesCm;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;InnerClasses$CaptureMe;true;yesCm;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;InnerClasses$CaptureMe;true;yesCm;(String);;Argument[0];ReturnValue;value;dfc-generated
|
||||
public String yesCm(String input) {
|
||||
return input;
|
||||
}
|
||||
}
|
||||
|
||||
// summary=p;InnerClasses;true;yes;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;InnerClasses;true;yes;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;InnerClasses;true;yes;(String);;Argument[0];ReturnValue;value;dfc-generated
|
||||
public String yes(String input) {
|
||||
return input;
|
||||
}
|
||||
|
||||
@@ -19,31 +19,31 @@ public final class InnerHolder {
|
||||
private StringBuilder sb = new StringBuilder();
|
||||
|
||||
// summary=p;InnerHolder;false;setContext;(String);;Argument[0];Argument[this];taint;df-generated
|
||||
// contentbased-summary=p;InnerHolder;false;setContext;(String);;Argument[0];Argument[this].SyntheticField[p.InnerHolder.context].SyntheticField[p.InnerHolder$Context.value];value;df-generated
|
||||
// contentbased-summary=p;InnerHolder;false;setContext;(String);;Argument[0];Argument[this].SyntheticField[p.InnerHolder.context].SyntheticField[p.InnerHolder$Context.value];value;dfc-generated
|
||||
public void setContext(String value) {
|
||||
context = new Context(value);
|
||||
}
|
||||
|
||||
// summary=p;InnerHolder;false;explicitSetContext;(String);;Argument[0];Argument[this];taint;df-generated
|
||||
// contentbased-summary=p;InnerHolder;false;explicitSetContext;(String);;Argument[0];Argument[this].SyntheticField[p.InnerHolder.context].SyntheticField[p.InnerHolder$Context.value];value;df-generated
|
||||
// contentbased-summary=p;InnerHolder;false;explicitSetContext;(String);;Argument[0];Argument[this].SyntheticField[p.InnerHolder.context].SyntheticField[p.InnerHolder$Context.value];value;dfc-generated
|
||||
public void explicitSetContext(String value) {
|
||||
this.context = new Context(value);
|
||||
}
|
||||
|
||||
// summary=p;InnerHolder;false;append;(String);;Argument[0];Argument[this];taint;df-generated
|
||||
// contentbased-summary=p;InnerHolder;false;append;(String);;Argument[0];Argument[this].SyntheticField[p.InnerHolder.sb];taint;df-generated
|
||||
// contentbased-summary=p;InnerHolder;false;append;(String);;Argument[0];Argument[this].SyntheticField[p.InnerHolder.sb];taint;dfc-generated
|
||||
public void append(String value) {
|
||||
sb.append(value);
|
||||
}
|
||||
|
||||
// summary=p;InnerHolder;false;getValue;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;InnerHolder;false;getValue;();;Argument[this].SyntheticField[p.InnerHolder.sb];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;InnerHolder;false;getValue;();;Argument[this].SyntheticField[p.InnerHolder.sb];ReturnValue;taint;dfc-generated
|
||||
public String getValue() {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
// summary=p;InnerHolder;false;getContextValue;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;InnerHolder;false;getContextValue;();;Argument[this].SyntheticField[p.InnerHolder.context].SyntheticField[p.InnerHolder$Context.value];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;InnerHolder;false;getContextValue;();;Argument[this].SyntheticField[p.InnerHolder.context].SyntheticField[p.InnerHolder$Context.value];ReturnValue;value;dfc-generated
|
||||
public String getContextValue() {
|
||||
return context.getValue();
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ public final class Joiner {
|
||||
private String emptyValue;
|
||||
|
||||
// summary=p;Joiner;false;Joiner;(CharSequence);;Argument[0];Argument[this];taint;df-generated
|
||||
// contentbased-summary=p;Joiner;false;Joiner;(CharSequence);;Argument[0];Argument[this].SyntheticField[p.Joiner.delimiter];taint;df-generated
|
||||
// contentbased-summary=p;Joiner;false;Joiner;(CharSequence);;Argument[0];Argument[this].SyntheticField[p.Joiner.delimiter];taint;dfc-generated
|
||||
public Joiner(CharSequence delimiter) {
|
||||
this(delimiter, "", "");
|
||||
}
|
||||
@@ -21,7 +21,7 @@ public final class Joiner {
|
||||
// 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
|
||||
// contentbased-summary=p;Joiner;false;Joiner;(CharSequence,CharSequence,CharSequence);;Argument[0];Argument[this].SyntheticField[p.Joiner.delimiter];taint;df-generated
|
||||
// contentbased-summary=p;Joiner;false;Joiner;(CharSequence,CharSequence,CharSequence);;Argument[0];Argument[this].SyntheticField[p.Joiner.delimiter];taint;dfc-generated
|
||||
// No content based summaries for prefix and suffix as they are "dead" synthetic fields.
|
||||
public Joiner(CharSequence delimiter, CharSequence prefix, CharSequence suffix) {
|
||||
Objects.requireNonNull(prefix, "The prefix must not be null");
|
||||
@@ -36,7 +36,7 @@ public final class Joiner {
|
||||
// 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
|
||||
// No content based summary as emptyValue is "dead" (synthetic)field.
|
||||
// contentbased-summary=p;Joiner;false;setEmptyValue;(CharSequence);;Argument[this];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;Joiner;false;setEmptyValue;(CharSequence);;Argument[this];ReturnValue;value;dfc-generated
|
||||
public Joiner setEmptyValue(CharSequence emptyValue) {
|
||||
this.emptyValue =
|
||||
Objects.requireNonNull(emptyValue, "The empty value must not be null").toString();
|
||||
@@ -44,7 +44,7 @@ public final class Joiner {
|
||||
}
|
||||
|
||||
// summary=p;Joiner;false;getDelimiter;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Joiner;false;getDelimiter;();;Argument[this].SyntheticField[p.Joiner.delimiter];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;Joiner;false;getDelimiter;();;Argument[this].SyntheticField[p.Joiner.delimiter];ReturnValue;value;dfc-generated
|
||||
public String getDelimiter() {
|
||||
return delimiter;
|
||||
}
|
||||
@@ -82,7 +82,7 @@ public final class Joiner {
|
||||
}
|
||||
|
||||
// summary=p;Joiner;false;add;(CharSequence);;Argument[this];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;Joiner;false;add;(CharSequence);;Argument[this];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;Joiner;false;add;(CharSequence);;Argument[this];ReturnValue;value;dfc-generated
|
||||
// MISSING content based summaries for "elts". This could be a synthetic field.
|
||||
public Joiner add(CharSequence newElement) {
|
||||
final String elt = String.valueOf(newElement);
|
||||
@@ -107,7 +107,7 @@ public final class Joiner {
|
||||
}
|
||||
|
||||
// summary=p;Joiner;false;merge;(Joiner);;Argument[this];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;Joiner;false;merge;(Joiner);;Argument[this];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;Joiner;false;merge;(Joiner);;Argument[this];ReturnValue;value;dfc-generated
|
||||
// MISSING content based summaries for "elts". This could be a synthetic field.
|
||||
public Joiner merge(Joiner other) {
|
||||
Objects.requireNonNull(other);
|
||||
|
||||
@@ -3,7 +3,7 @@ package p;
|
||||
public class MultiPaths {
|
||||
|
||||
// summary=p;MultiPaths;true;cond;(String,String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;MultiPaths;true;cond;(String,String);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;MultiPaths;true;cond;(String,String);;Argument[0];ReturnValue;value;dfc-generated
|
||||
public String cond(String x, String other) {
|
||||
if (x == other) {
|
||||
return x.substring(0, 100);
|
||||
|
||||
@@ -17,7 +17,7 @@ class MultipleImpl2 {
|
||||
|
||||
public class Impl2 implements IInterface {
|
||||
// summary=p;MultipleImpl2$IInterface;true;m;(Object);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;MultipleImpl2$IInterface;true;m;(Object);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;MultipleImpl2$IInterface;true;m;(Object);;Argument[0];ReturnValue;value;dfc-generated
|
||||
public Object m(Object value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ public class MultipleImpls {
|
||||
|
||||
public static class Strat1 implements Strategy {
|
||||
// summary=p;MultipleImpls$Strategy;true;doSomething;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;MultipleImpls$Strategy;true;doSomething;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;MultipleImpls$Strategy;true;doSomething;(String);;Argument[0];ReturnValue;value;dfc-generated
|
||||
public String doSomething(String value) {
|
||||
return value;
|
||||
}
|
||||
@@ -31,7 +31,7 @@ public class MultipleImpls {
|
||||
|
||||
// summary=p;MultipleImpls$Strategy;true;doSomething;(String);;Argument[0];Argument[this];taint;df-generated
|
||||
// The content based summary is not lifted as it pertains to a (synthetic)field.
|
||||
// contentbased-summary=p;MultipleImpls$Strat2;true;doSomething;(String);;Argument[0];Argument[this].SyntheticField[p.MultipleImpls$Strat2.foo];value;df-generated
|
||||
// contentbased-summary=p;MultipleImpls$Strat2;true;doSomething;(String);;Argument[0];Argument[this].SyntheticField[p.MultipleImpls$Strat2.foo];value;dfc-generated
|
||||
public String doSomething(String value) {
|
||||
this.foo = value;
|
||||
return "none";
|
||||
@@ -39,7 +39,7 @@ public class MultipleImpls {
|
||||
|
||||
// summary=p;MultipleImpls$Strat2;true;getValue;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// The content based summary is not lifted as it pertains to a (synthetic)field.
|
||||
// contentbased-summary=p;MultipleImpls$Strat2;true;getValue;();;Argument[this].SyntheticField[p.MultipleImpls$Strat2.foo];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;MultipleImpls$Strat2;true;getValue;();;Argument[this].SyntheticField[p.MultipleImpls$Strat2.foo];ReturnValue;value;dfc-generated
|
||||
public String getValue() {
|
||||
return this.foo;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import java.util.List;
|
||||
public class ParamFlow {
|
||||
|
||||
// summary=p;ParamFlow;true;returnsInput;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;returnsInput;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;returnsInput;(String);;Argument[0];ReturnValue;value;dfc-generated
|
||||
public String returnsInput(String input) {
|
||||
return input;
|
||||
}
|
||||
@@ -20,8 +20,8 @@ public class ParamFlow {
|
||||
|
||||
// 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
|
||||
// contentbased-summary=p;ParamFlow;true;returnMultipleParameters;(String,String);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;returnMultipleParameters;(String,String);;Argument[1];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;returnMultipleParameters;(String,String);;Argument[0];ReturnValue;value;dfc-generated
|
||||
// contentbased-summary=p;ParamFlow;true;returnMultipleParameters;(String,String);;Argument[1];ReturnValue;value;dfc-generated
|
||||
public String returnMultipleParameters(String one, String two) {
|
||||
if (System.currentTimeMillis() > 100) {
|
||||
return two;
|
||||
@@ -30,31 +30,31 @@ public class ParamFlow {
|
||||
}
|
||||
|
||||
// summary=p;ParamFlow;true;returnArrayElement;(String[]);;Argument[0].ArrayElement;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;returnArrayElement;(String[]);;Argument[0].ArrayElement;ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;returnArrayElement;(String[]);;Argument[0].ArrayElement;ReturnValue;value;dfc-generated
|
||||
public String returnArrayElement(String[] input) {
|
||||
return input[0];
|
||||
}
|
||||
|
||||
// summary=p;ParamFlow;true;returnVarArgElement;(String[]);;Argument[0].ArrayElement;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;returnVarArgElement;(String[]);;Argument[0].ArrayElement;ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;returnVarArgElement;(String[]);;Argument[0].ArrayElement;ReturnValue;value;dfc-generated
|
||||
public String returnVarArgElement(String... input) {
|
||||
return input[0];
|
||||
}
|
||||
|
||||
// summary=p;ParamFlow;true;returnCollectionElement;(List);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;returnCollectionElement;(List);;Argument[0].Element;ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;returnCollectionElement;(List);;Argument[0].Element;ReturnValue;value;dfc-generated
|
||||
public String returnCollectionElement(List<String> input) {
|
||||
return input.get(0);
|
||||
}
|
||||
|
||||
// summary=p;ParamFlow;true;returnIteratorElement;(Iterator);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;returnIteratorElement;(Iterator);;Argument[0].Element;ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;returnIteratorElement;(Iterator);;Argument[0].Element;ReturnValue;value;dfc-generated
|
||||
public String returnIteratorElement(Iterator<String> input) {
|
||||
return input.next();
|
||||
}
|
||||
|
||||
// summary=p;ParamFlow;true;returnIterableElement;(Iterable);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;returnIterableElement;(Iterable);;Argument[0].Element;ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;returnIterableElement;(Iterable);;Argument[0].Element;ReturnValue;value;dfc-generated
|
||||
public String returnIterableElement(Iterable<String> input) {
|
||||
return input.iterator().next();
|
||||
}
|
||||
@@ -65,19 +65,19 @@ public class ParamFlow {
|
||||
}
|
||||
|
||||
// summary=p;ParamFlow;true;writeChunked;(byte[],OutputStream);;Argument[0];Argument[1];taint;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;writeChunked;(byte[],OutputStream);;Argument[0];Argument[1];taint;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;writeChunked;(byte[],OutputStream);;Argument[0];Argument[1];taint;dfc-generated
|
||||
public void writeChunked(byte[] data, OutputStream output) throws IOException {
|
||||
output.write(data, 0, data.length);
|
||||
}
|
||||
|
||||
// summary=p;ParamFlow;true;writeChunked;(char[],OutputStream);;Argument[0];Argument[1];taint;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;writeChunked;(char[],OutputStream);;Argument[0];Argument[1];taint;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;writeChunked;(char[],OutputStream);;Argument[0];Argument[1];taint;dfc-generated
|
||||
public void writeChunked(char[] data, OutputStream output) throws IOException {
|
||||
output.write(String.valueOf(data).getBytes(), 0, data.length);
|
||||
}
|
||||
|
||||
// summary=p;ParamFlow;true;addTo;(String,List);;Argument[0];Argument[1].Element;taint;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;addTo;(String,List);;Argument[0];Argument[1].Element;value;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;addTo;(String,List);;Argument[0];Argument[1].Element;value;dfc-generated
|
||||
public void addTo(String data, List<String> target) {
|
||||
target.add(data);
|
||||
}
|
||||
|
||||
@@ -34,21 +34,21 @@ public final class Pojo {
|
||||
|
||||
// summary=p;Pojo;false;Pojo;(Byte[],char[]);;Argument[0];Argument[this];taint;df-generated
|
||||
// summary=p;Pojo;false;Pojo;(Byte[],char[]);;Argument[1];Argument[this];taint;df-generated
|
||||
// contentbased-summary=p;Pojo;false;Pojo;(Byte[],char[]);;Argument[0];Argument[this].SyntheticField[p.Pojo.byteObjectArray];value;df-generated
|
||||
// contentbased-summary=p;Pojo;false;Pojo;(Byte[],char[]);;Argument[1];Argument[this].SyntheticField[p.Pojo.charArray];value;df-generated
|
||||
// contentbased-summary=p;Pojo;false;Pojo;(Byte[],char[]);;Argument[0];Argument[this].SyntheticField[p.Pojo.byteObjectArray];value;dfc-generated
|
||||
// contentbased-summary=p;Pojo;false;Pojo;(Byte[],char[]);;Argument[1];Argument[this].SyntheticField[p.Pojo.charArray];value;dfc-generated
|
||||
public Pojo(Byte[] byteObjectArray, char[] charArray) {
|
||||
this.byteObjectArray = byteObjectArray;
|
||||
this.charArray = charArray;
|
||||
}
|
||||
|
||||
// summary=p;Pojo;false;getValue;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Pojo;false;getValue;();;Argument[this].SyntheticField[p.Pojo.value];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;Pojo;false;getValue;();;Argument[this].SyntheticField[p.Pojo.value];ReturnValue;value;dfc-generated
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
// summary=p;Pojo;false;setValue;(String);;Argument[0];Argument[this];taint;df-generated
|
||||
// contentbased-summary=p;Pojo;false;setValue;(String);;Argument[0];Argument[this].SyntheticField[p.Pojo.value];value;df-generated
|
||||
// contentbased-summary=p;Pojo;false;setValue;(String);;Argument[0];Argument[this].SyntheticField[p.Pojo.value];value;dfc-generated
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
@@ -75,19 +75,19 @@ public final class Pojo {
|
||||
}
|
||||
|
||||
// summary=p;Pojo;false;getCharArray;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Pojo;false;getCharArray;();;Argument[this].SyntheticField[p.Pojo.charArray];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;Pojo;false;getCharArray;();;Argument[this].SyntheticField[p.Pojo.charArray];ReturnValue;value;dfc-generated
|
||||
public char[] getCharArray() {
|
||||
return charArray;
|
||||
}
|
||||
|
||||
// summary=p;Pojo;false;getByteArray;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Pojo;false;getByteArray;();;Argument[this].Field[p.Pojo.byteArray];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;Pojo;false;getByteArray;();;Argument[this].Field[p.Pojo.byteArray];ReturnValue;value;dfc-generated
|
||||
public byte[] getByteArray() {
|
||||
return byteArray;
|
||||
}
|
||||
|
||||
// summary=p;Pojo;false;setByteArray;(byte[]);;Argument[0];Argument[this];taint;df-generated
|
||||
// contentbased-summary=p;Pojo;false;setByteArray;(byte[]);;Argument[0];Argument[this].Field[p.Pojo.byteArray];value;df-generated
|
||||
// contentbased-summary=p;Pojo;false;setByteArray;(byte[]);;Argument[0];Argument[this].Field[p.Pojo.byteArray];value;dfc-generated
|
||||
public void setByteArray(byte[] value) {
|
||||
byteArray = value;
|
||||
}
|
||||
@@ -114,7 +114,7 @@ public final class Pojo {
|
||||
}
|
||||
|
||||
// summary=p;Pojo;false;getBoxedBytes;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Pojo;false;getBoxedBytes;();;Argument[this].SyntheticField[p.Pojo.byteObjectArray];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;Pojo;false;getBoxedBytes;();;Argument[this].SyntheticField[p.Pojo.byteObjectArray];ReturnValue;value;dfc-generated
|
||||
public Byte[] getBoxedBytes() {
|
||||
return byteObjectArray;
|
||||
}
|
||||
@@ -130,25 +130,25 @@ public final class Pojo {
|
||||
}
|
||||
|
||||
// summary=p;Pojo;false;fillIn;(List);;Argument[this];Argument[0].Element;taint;df-generated
|
||||
// contentbased-summary=p;Pojo;false;fillIn;(List);;Argument[this].SyntheticField[p.Pojo.value];Argument[0].Element;value;df-generated
|
||||
// contentbased-summary=p;Pojo;false;fillIn;(List);;Argument[this].SyntheticField[p.Pojo.value];Argument[0].Element;value;dfc-generated
|
||||
public void fillIn(List<String> target) {
|
||||
target.add(value);
|
||||
}
|
||||
|
||||
// summary=p;Pojo;false;setStringValue1;(String);;Argument[0];Argument[this];taint;df-generated
|
||||
// contentbased-summary=p;Pojo;false;setStringValue1;(String);;Argument[0];Argument[this].SyntheticField[p.Pojo.stringValue1];value;df-generated
|
||||
// contentbased-summary=p;Pojo;false;setStringValue1;(String);;Argument[0];Argument[this].SyntheticField[p.Pojo.stringValue1];value;dfc-generated
|
||||
public void setStringValue1(String value) {
|
||||
this.stringValue1 = value;
|
||||
}
|
||||
|
||||
// neutral=p;Pojo;copyStringValue;();summary;df-generated
|
||||
// contentbased-summary=p;Pojo;false;copyStringValue;();;Argument[this].SyntheticField[p.Pojo.stringValue1];Argument[this].SyntheticField[p.Pojo.stringValue2];value;df-generated
|
||||
// contentbased-summary=p;Pojo;false;copyStringValue;();;Argument[this].SyntheticField[p.Pojo.stringValue1];Argument[this].SyntheticField[p.Pojo.stringValue2];value;dfc-generated
|
||||
public void copyStringValue() {
|
||||
this.stringValue2 = this.stringValue1;
|
||||
}
|
||||
|
||||
// summary=p;Pojo;false;getStringValue2;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Pojo;false;getStringValue2;();;Argument[this].SyntheticField[p.Pojo.stringValue2];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;Pojo;false;getStringValue2;();;Argument[this].SyntheticField[p.Pojo.stringValue2];ReturnValue;value;dfc-generated
|
||||
public String getStringValue2() {
|
||||
return this.stringValue2;
|
||||
}
|
||||
@@ -157,20 +157,20 @@ public final class Pojo {
|
||||
private String value;
|
||||
|
||||
// summary=p;Pojo$InnerPojo;true;InnerPojo;(String);;Argument[0];Argument[this];taint;df-generated
|
||||
// contentbased-summary=p;Pojo$InnerPojo;true;InnerPojo;(String);;Argument[0];Argument[this].SyntheticField[p.Pojo$InnerPojo.value];value;df-generated
|
||||
// contentbased-summary=p;Pojo$InnerPojo;true;InnerPojo;(String);;Argument[0];Argument[this].SyntheticField[p.Pojo$InnerPojo.value];value;dfc-generated
|
||||
public InnerPojo(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
// summary=p;Pojo$InnerPojo;true;getValue;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Pojo$InnerPojo;true;getValue;();;Argument[this].SyntheticField[p.Pojo$InnerPojo.value];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;Pojo$InnerPojo;true;getValue;();;Argument[this].SyntheticField[p.Pojo$InnerPojo.value];ReturnValue;value;dfc-generated
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
// summary=p;Pojo;false;makeInnerPojo;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Pojo;false;makeInnerPojo;(String);;Argument[0];ReturnValue.SyntheticField[p.Pojo$InnerPojo.value];value;df-generated
|
||||
// contentbased-summary=p;Pojo;false;makeInnerPojo;(String);;Argument[0];ReturnValue.SyntheticField[p.Pojo$InnerPojo.value];value;dfc-generated
|
||||
public InnerPojo makeInnerPojo(String value) {
|
||||
return new InnerPojo(value);
|
||||
}
|
||||
|
||||
@@ -29,9 +29,6 @@ public class PrivateFlowViaPublicInterface {
|
||||
}
|
||||
|
||||
// summary=p;PrivateFlowViaPublicInterface$SPI;true;openStream;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// This summary shouldn't be created because the method is private.
|
||||
// This is most likely because the lifting logic hasn't been properly adapted.
|
||||
// SPURIOUS-contentbased-summary=p;PrivateFlowViaPublicInterface$PrivateImplWithSink;false;openStream;();;Argument[this].SyntheticField[p.PrivateFlowViaPublicInterface$PrivateImplWithSink.file];ReturnValue;taint;df-generated
|
||||
@Override
|
||||
public OutputStream openStream() throws IOException {
|
||||
return new FileOutputStream(file);
|
||||
@@ -54,7 +51,7 @@ public class PrivateFlowViaPublicInterface {
|
||||
}
|
||||
|
||||
// summary=p;PrivateFlowViaPublicInterface;true;createAnSPI;(File);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;PrivateFlowViaPublicInterface;true;createAnSPI;(File);;Argument[0];ReturnValue.SyntheticField[p.PrivateFlowViaPublicInterface$PrivateImplWithSink.file];value;df-generated
|
||||
// contentbased-summary=p;PrivateFlowViaPublicInterface;true;createAnSPI;(File);;Argument[0];ReturnValue.SyntheticField[p.PrivateFlowViaPublicInterface$PrivateImplWithSink.file];value;dfc-generated
|
||||
public static SPI createAnSPI(File file) {
|
||||
return new PrivateImplWithSink(file);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package p;
|
||||
|
||||
public class SyntheticCollections {
|
||||
private String[] array;
|
||||
|
||||
// summary=p;SyntheticCollections;true;SyntheticCollections;(String[]);;Argument[0].ArrayElement;Argument[this];taint;df-generated
|
||||
// contentbased-summary=p;SyntheticCollections;true;SyntheticCollections;(String[]);;Argument[0];Argument[this].SyntheticField[p.SyntheticCollections.array];value;dfc-generated
|
||||
public SyntheticCollections(String[] array) {
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
// summary=p;SyntheticCollections;true;getElement;(Integer);;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;SyntheticCollections;true;getElement;(Integer);;Argument[this].SyntheticField[p.SyntheticCollections.array].ArrayElement;ReturnValue;value;dfc-generated
|
||||
public String getElement(Integer index) {
|
||||
return array[index];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user