mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge pull request #17330 from michaelnebel/java/modelgenfieldbased
Java/C#: Field based model generator (Experimental).
This commit is contained in:
@@ -18,17 +18,35 @@ private class ReturnNodeExt extends DataFlow::Node {
|
||||
kind = DataFlowImplCommon::getParamReturnPosition(this, _).getKind()
|
||||
}
|
||||
|
||||
string getOutput() {
|
||||
kind instanceof DataFlowImplCommon::ValueReturnKind and
|
||||
/**
|
||||
* Gets the kind of the return node.
|
||||
*/
|
||||
DataFlowImplCommon::ReturnKindExt getKind() { result = kind }
|
||||
}
|
||||
|
||||
bindingset[c]
|
||||
private signature string printCallableParamSig(Callable c, ParameterPosition p);
|
||||
|
||||
private module PrintReturnNodeExt<printCallableParamSig/2 printCallableParam> {
|
||||
string getOutput(ReturnNodeExt node) {
|
||||
node.getKind() instanceof DataFlowImplCommon::ValueReturnKind and
|
||||
result = "ReturnValue"
|
||||
or
|
||||
exists(ParameterPosition pos |
|
||||
pos = kind.(DataFlowImplCommon::ParamUpdateReturnKind).getPosition() and
|
||||
result = paramReturnNodeAsOutput(returnNodeEnclosingCallable(this), pos)
|
||||
pos = node.getKind().(DataFlowImplCommon::ParamUpdateReturnKind).getPosition() and
|
||||
result = printCallableParam(returnNodeEnclosingCallable(node), pos)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
string getOutput(ReturnNodeExt node) {
|
||||
result = PrintReturnNodeExt<paramReturnNodeAsOutput/2>::getOutput(node)
|
||||
}
|
||||
|
||||
string getContentOutput(ReturnNodeExt node) {
|
||||
result = PrintReturnNodeExt<paramReturnNodeAsContentOutput/2>::getOutput(node)
|
||||
}
|
||||
|
||||
class DataFlowSummaryTargetApi extends SummaryTargetApi {
|
||||
DataFlowSummaryTargetApi() { not isUninterestingForDataFlowModels(this) }
|
||||
}
|
||||
@@ -71,7 +89,8 @@ private predicate isRelevantTaintStep(DataFlow::Node node1, DataFlow::Node node2
|
||||
* Holds if content `c` is either a field, a synthetic field or language specific
|
||||
* content of a relevant type or a container like content.
|
||||
*/
|
||||
private predicate isRelevantContent(DataFlow::ContentSet c) {
|
||||
pragma[nomagic]
|
||||
private predicate isRelevantContent0(DataFlow::ContentSet c) {
|
||||
isRelevantTypeInContent(c) or
|
||||
containerContent(c)
|
||||
}
|
||||
@@ -85,6 +104,16 @@ string parameterNodeAsInput(DataFlow::ParameterNode p) {
|
||||
result = qualifierString() and p instanceof InstanceParameterNode
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MaD string representation of the parameter `p`
|
||||
* when used in content flow.
|
||||
*/
|
||||
string parameterNodeAsContentInput(DataFlow::ParameterNode p) {
|
||||
result = parameterContentAccess(p.asParameter())
|
||||
or
|
||||
result = qualifierString() and p instanceof InstanceParameterNode
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MaD input string representation of `source`.
|
||||
*/
|
||||
@@ -170,7 +199,7 @@ module PropagateFlowConfig implements DataFlow::StateConfigSig {
|
||||
) {
|
||||
exists(DataFlow::ContentSet c |
|
||||
DataFlowImplCommon::store(node1, c.getAStoreContent(), node2, _, _) and
|
||||
isRelevantContent(c) and
|
||||
isRelevantContent0(c) and
|
||||
(
|
||||
state1 instanceof TaintRead and state2.(TaintStore).getStep() = 1
|
||||
or
|
||||
@@ -180,7 +209,7 @@ module PropagateFlowConfig implements DataFlow::StateConfigSig {
|
||||
or
|
||||
exists(DataFlow::ContentSet c |
|
||||
DataFlowPrivate::readStep(node1, c, node2) and
|
||||
isRelevantContent(c) and
|
||||
isRelevantContent0(c) and
|
||||
state1.(TaintRead).getStep() + 1 = state2.(TaintRead).getStep()
|
||||
)
|
||||
}
|
||||
@@ -196,6 +225,9 @@ module PropagateFlowConfig implements DataFlow::StateConfigSig {
|
||||
|
||||
module PropagateFlow = TaintTracking::GlobalWithState<PropagateFlowConfig>;
|
||||
|
||||
/**
|
||||
* Gets the summary model(s) of `api`, if there is flow from parameters to return value or parameter.
|
||||
*/
|
||||
string captureThroughFlow0(
|
||||
DataFlowSummaryTargetApi api, DataFlow::ParameterNode p, ReturnNodeExt returnNodeExt
|
||||
) {
|
||||
@@ -203,7 +235,7 @@ string captureThroughFlow0(
|
||||
p.getEnclosingCallable() = api and
|
||||
returnNodeExt.(DataFlow::Node).getEnclosingCallable() = api and
|
||||
input = parameterNodeAsInput(p) and
|
||||
output = returnNodeExt.getOutput() and
|
||||
output = getOutput(returnNodeExt) and
|
||||
input != output and
|
||||
result = Printing::asTaintModel(api, input, output)
|
||||
)
|
||||
@@ -219,6 +251,69 @@ string captureThroughFlow(DataFlowSummaryTargetApi api) {
|
||||
)
|
||||
}
|
||||
|
||||
private module PropagateContentFlowConfig implements ContentDataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
source instanceof DataFlow::ParameterNode and
|
||||
source.getEnclosingCallable() instanceof DataFlowSummaryTargetApi
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
sink instanceof ReturnNodeExt and
|
||||
sink.getEnclosingCallable() instanceof DataFlowSummaryTargetApi
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep = isAdditionalContentFlowStep/2;
|
||||
|
||||
predicate isBarrier(DataFlow::Node n) {
|
||||
exists(Type t | t = n.getType() and not isRelevantType(t))
|
||||
}
|
||||
|
||||
int accessPathLimit() { result = 2 }
|
||||
|
||||
predicate isRelevantContent(DataFlow::ContentSet s) { isRelevantContent0(s) }
|
||||
|
||||
DataFlow::FlowFeature getAFeature() {
|
||||
result instanceof DataFlow::FeatureEqualSourceSinkCallContext
|
||||
}
|
||||
}
|
||||
|
||||
private module PropagateContentFlow = ContentDataFlow::Global<PropagateContentFlowConfig>;
|
||||
|
||||
private string getContent(PropagateContentFlow::AccessPath ap, int i) {
|
||||
exists(ContentSet head, PropagateContentFlow::AccessPath tail |
|
||||
head = ap.getHead() and
|
||||
tail = ap.getTail()
|
||||
|
|
||||
i = 0 and
|
||||
result = "." + printContent(head)
|
||||
or
|
||||
i > 0 and result = getContent(tail, i - 1)
|
||||
)
|
||||
}
|
||||
|
||||
private string printStoreAccessPath(PropagateContentFlow::AccessPath ap) {
|
||||
result = concat(int i | | getContent(ap, i), "" order by i)
|
||||
}
|
||||
|
||||
private string printReadAccessPath(PropagateContentFlow::AccessPath ap) {
|
||||
result = concat(int i | | getContent(ap, i), "" order by i desc)
|
||||
}
|
||||
|
||||
string captureContentFlow(DataFlowSummaryTargetApi api) {
|
||||
exists(
|
||||
DataFlow::ParameterNode p, ReturnNodeExt returnNodeExt, string input, string output,
|
||||
PropagateContentFlow::AccessPath reads, PropagateContentFlow::AccessPath stores,
|
||||
boolean preservesValue
|
||||
|
|
||||
PropagateContentFlow::flow(p, reads, returnNodeExt, stores, preservesValue) and
|
||||
returnNodeExt.getEnclosingCallable() = api and
|
||||
input = parameterNodeAsContentInput(p) + printReadAccessPath(reads) and
|
||||
output = getContentOutput(returnNodeExt) + printStoreAccessPath(stores) and
|
||||
input != output and
|
||||
result = Printing::asModel(api, input, output, preservesValue)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A dataflow configuration used for finding new sources.
|
||||
* The sources are the already known existing sources and the sinks are the API return nodes.
|
||||
@@ -261,7 +356,7 @@ string captureSource(DataFlowSourceTargetApi api) {
|
||||
ExternalFlow::sourceNode(source, kind) and
|
||||
api = sink.getEnclosingCallable() and
|
||||
not irrelevantSourceSinkApi(source.getEnclosingCallable(), api) and
|
||||
result = Printing::asSourceModel(api, sink.getOutput(), kind)
|
||||
result = Printing::asSourceModel(api, getOutput(sink), kind)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -5,11 +5,14 @@
|
||||
private import csharp as CS
|
||||
private import semmle.code.csharp.commons.Util as Util
|
||||
private import semmle.code.csharp.commons.Collections as Collections
|
||||
private import semmle.code.csharp.commons.QualifiedName as QualifiedName
|
||||
private import semmle.code.csharp.dataflow.internal.DataFlowDispatch
|
||||
private import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
|
||||
private import semmle.code.csharp.frameworks.system.linq.Expressions
|
||||
private import semmle.code.csharp.frameworks.System
|
||||
private import semmle.code.csharp.dataflow.internal.TaintTrackingPrivate as TaintTrackingPrivate
|
||||
import semmle.code.csharp.dataflow.internal.ExternalFlow as ExternalFlow
|
||||
import semmle.code.csharp.dataflow.internal.ContentDataFlow as ContentDataFlow
|
||||
import semmle.code.csharp.dataflow.internal.DataFlowImplCommon as DataFlowImplCommon
|
||||
import semmle.code.csharp.dataflow.internal.DataFlowPrivate as DataFlowPrivate
|
||||
import semmle.code.csharp.dataflow.internal.DataFlowDispatch as DataFlowDispatch
|
||||
@@ -22,6 +25,8 @@ class Type = CS::Type;
|
||||
|
||||
class Callable = CS::Callable;
|
||||
|
||||
class ContentSet = DataFlow::ContentSet;
|
||||
|
||||
/**
|
||||
* Holds if any of the parameters of `api` are `System.Func<>`.
|
||||
*/
|
||||
@@ -241,20 +246,40 @@ string parameterAccess(CS::Parameter p) {
|
||||
else result = "Argument[" + p.getPosition() + "]"
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MaD string representation of the parameter `p`
|
||||
* when used in content flow.
|
||||
*/
|
||||
string parameterContentAccess(CS::Parameter p) { result = "Argument[" + p.getPosition() + "]" }
|
||||
|
||||
class InstanceParameterNode = DataFlowPrivate::InstanceParameterNode;
|
||||
|
||||
class ParameterPosition = DataFlowDispatch::ParameterPosition;
|
||||
|
||||
private signature string parameterAccessSig(Parameter p);
|
||||
|
||||
module ParamReturnNodeAsOutput<parameterAccessSig/1 getParamAccess> {
|
||||
bindingset[c]
|
||||
string paramReturnNodeAsOutput(CS::Callable c, ParameterPosition pos) {
|
||||
result = getParamAccess(c.getParameter(pos.getPosition()))
|
||||
or
|
||||
pos.isThisParameter() and
|
||||
result = qualifierString()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MaD string representation of return through parameter at position
|
||||
* `pos` of callable `c`.
|
||||
*/
|
||||
bindingset[c]
|
||||
string paramReturnNodeAsOutput(CS::Callable c, ParameterPosition pos) {
|
||||
result = parameterAccess(c.getParameter(pos.getPosition()))
|
||||
or
|
||||
pos.isThisParameter() and
|
||||
result = qualifierString()
|
||||
result = ParamReturnNodeAsOutput<parameterAccess/1>::paramReturnNodeAsOutput(c, pos)
|
||||
}
|
||||
|
||||
bindingset[c]
|
||||
string paramReturnNodeAsContentOutput(Callable c, ParameterPosition pos) {
|
||||
result = ParamReturnNodeAsOutput<parameterContentAccess/1>::paramReturnNodeAsOutput(c, pos)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -344,3 +369,44 @@ predicate isRelevantSourceKind(string kind) { any() }
|
||||
* Holds if the the content `c` is a container.
|
||||
*/
|
||||
predicate containerContent(DataFlow::ContentSet c) { c.isElement() }
|
||||
|
||||
/**
|
||||
* Holds if there is a taint step from `node1` to `node2` in content flow.
|
||||
*/
|
||||
predicate isAdditionalContentFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||
TaintTrackingPrivate::defaultAdditionalTaintStep(nodeFrom, nodeTo, _) and
|
||||
not nodeTo.asExpr() instanceof CS::ElementAccess and
|
||||
not exists(DataFlow::ContentSet c |
|
||||
DataFlowPrivate::readStep(nodeFrom, c, nodeTo) and containerContent(c)
|
||||
)
|
||||
}
|
||||
|
||||
bindingset[d]
|
||||
private string getFullyQualifiedName(Declaration d) {
|
||||
exists(string qualifier, string name |
|
||||
d.hasFullyQualifiedName(qualifier, name) and
|
||||
result = QualifiedName::getQualifiedName(qualifier, name)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MaD string representation of the contentset `c`.
|
||||
*/
|
||||
string printContent(DataFlow::ContentSet c) {
|
||||
exists(CS::Field f, string name | name = getFullyQualifiedName(f) |
|
||||
c.isField(f) and
|
||||
if f.isEffectivelyPublic()
|
||||
then result = "Field[" + name + "]"
|
||||
else result = "SyntheticField[" + name + "]"
|
||||
)
|
||||
or
|
||||
exists(CS::Property p, string name | name = getFullyQualifiedName(p) |
|
||||
c.isProperty(p) and
|
||||
if p.isEffectivelyPublic()
|
||||
then result = "Property[" + name + "]"
|
||||
else result = "SyntheticField[" + name + "]"
|
||||
)
|
||||
or
|
||||
c.isElement() and
|
||||
result = "Element"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
unexpectedModel
|
||||
expectedModel
|
||||
@@ -0,0 +1,12 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/csharp-all
|
||||
extensible: summaryModel
|
||||
data:
|
||||
- [ "Models", "ManuallyModelled", False, "HasSummary", "(System.Object)", "", "Argument[0]", "ReturnValue", "value", "manual"]
|
||||
|
||||
- addsTo:
|
||||
pack: codeql/csharp-all
|
||||
extensible: neutralModel
|
||||
data:
|
||||
- [ "Models", "ManuallyModelled", "HasNeutralSummary", "(System.Object)", "summary", "manual"]
|
||||
@@ -0,0 +1,11 @@
|
||||
import csharp
|
||||
import utils.modelgenerator.internal.CaptureModels
|
||||
import TestUtilities.InlineMadTest
|
||||
|
||||
module InlineMadTestConfig implements InlineMadTestConfigSig {
|
||||
string getCapturedModel(Callable c) { result = captureContentFlow(c) }
|
||||
|
||||
string getKind() { result = "contentbased-summary" }
|
||||
}
|
||||
|
||||
import InlineMadTest<InlineMadTestConfig>
|
||||
@@ -13,18 +13,21 @@ public class BasicFlow
|
||||
private string tainted;
|
||||
|
||||
// summary=Models;BasicFlow;false;ReturnThis;(System.Object);;Argument[this];ReturnValue;value;df-generated
|
||||
// contentbased-summary=Models;BasicFlow;false;ReturnThis;(System.Object);;Argument[this];ReturnValue;value;df-generated
|
||||
public BasicFlow ReturnThis(object input)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
// summary=Models;BasicFlow;false;ReturnParam0;(System.String,System.Object);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;BasicFlow;false;ReturnParam0;(System.String,System.Object);;Argument[0];ReturnValue;value;df-generated
|
||||
public string ReturnParam0(string input0, object input1)
|
||||
{
|
||||
return input0;
|
||||
}
|
||||
|
||||
// summary=Models;BasicFlow;false;ReturnParam1;(System.String,System.Object);;Argument[1];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;BasicFlow;false;ReturnParam1;(System.String,System.Object);;Argument[1];ReturnValue;value;df-generated
|
||||
public object ReturnParam1(string input0, object input1)
|
||||
{
|
||||
return input1;
|
||||
@@ -32,24 +35,29 @@ public class BasicFlow
|
||||
|
||||
// summary=Models;BasicFlow;false;ReturnParamMultiple;(System.Object,System.Object);;Argument[0];ReturnValue;taint;df-generated
|
||||
// summary=Models;BasicFlow;false;ReturnParamMultiple;(System.Object,System.Object);;Argument[1];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;BasicFlow;false;ReturnParamMultiple;(System.Object,System.Object);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=Models;BasicFlow;false;ReturnParamMultiple;(System.Object,System.Object);;Argument[1];ReturnValue;value;df-generated
|
||||
public object ReturnParamMultiple(object input0, object input1)
|
||||
{
|
||||
return (System.DateTime.Now.DayOfWeek == System.DayOfWeek.Monday) ? input0 : input1;
|
||||
}
|
||||
|
||||
// summary=Models;BasicFlow;false;ReturnSubstring;(System.String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;BasicFlow;false;ReturnSubstring;(System.String);;Argument[0];ReturnValue;taint;df-generated
|
||||
public string ReturnSubstring(string s)
|
||||
{
|
||||
return s.Substring(0, 1);
|
||||
}
|
||||
|
||||
// summary=Models;BasicFlow;false;SetField;(System.String);;Argument[0];Argument[this];taint;df-generated
|
||||
// contentbased-summary=Models;BasicFlow;false;SetField;(System.String);;Argument[0];Argument[this].SyntheticField[Models.BasicFlow.tainted];value;df-generated
|
||||
public void SetField(string s)
|
||||
{
|
||||
tainted = s;
|
||||
}
|
||||
|
||||
// summary=Models;BasicFlow;false;ReturnField;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;BasicFlow;false;ReturnField;();;Argument[this].SyntheticField[Models.BasicFlow.tainted];ReturnValue;value;df-generated
|
||||
public string ReturnField()
|
||||
{
|
||||
return tainted;
|
||||
@@ -61,72 +69,84 @@ public class CollectionFlow
|
||||
private string tainted;
|
||||
|
||||
// summary=Models;CollectionFlow;false;ReturnArrayElement;(System.Object[]);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;CollectionFlow;false;ReturnArrayElement;(System.Object[]);;Argument[0].Element;ReturnValue;value;df-generated
|
||||
public object ReturnArrayElement(object[] input)
|
||||
{
|
||||
return input[0];
|
||||
}
|
||||
|
||||
// summary=Models;CollectionFlow;false;AssignToArray;(System.Object,System.Object[]);;Argument[0];Argument[1].Element;taint;df-generated
|
||||
// contentbased-summary=Models;CollectionFlow;false;AssignToArray;(System.Object,System.Object[]);;Argument[0];Argument[1].Element;value;df-generated
|
||||
public void AssignToArray(object data, object[] target)
|
||||
{
|
||||
target[0] = data;
|
||||
}
|
||||
|
||||
// summary=Models;CollectionFlow;false;AssignFieldToArray;(System.Object[]);;Argument[this];Argument[0].Element;taint;df-generated
|
||||
// contentbased-summary=Models;CollectionFlow;false;AssignFieldToArray;(System.Object[]);;Argument[this].SyntheticField[Models.CollectionFlow.tainted];Argument[0].Element;value;df-generated
|
||||
public void AssignFieldToArray(object[] target)
|
||||
{
|
||||
target[0] = tainted;
|
||||
}
|
||||
|
||||
// summary=Models;CollectionFlow;false;ReturnListElement;(System.Collections.Generic.List<System.Object>);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;CollectionFlow;false;ReturnListElement;(System.Collections.Generic.List<System.Object>);;Argument[0].Element;ReturnValue;value;df-generated
|
||||
public object ReturnListElement(List<object> input)
|
||||
{
|
||||
return input[0];
|
||||
}
|
||||
|
||||
// summary=Models;CollectionFlow;false;AddToList;(System.Collections.Generic.List<System.Object>,System.Object);;Argument[1];Argument[0].Element;taint;df-generated
|
||||
// contentbased-summary=Models;CollectionFlow;false;AddToList;(System.Collections.Generic.List<System.Object>,System.Object);;Argument[1];Argument[0].Element;value;df-generated
|
||||
public void AddToList(List<object> input, object data)
|
||||
{
|
||||
input.Add(data);
|
||||
}
|
||||
|
||||
// summary=Models;CollectionFlow;false;AddFieldToList;(System.Collections.Generic.List<System.String>);;Argument[this];Argument[0].Element;taint;df-generated
|
||||
// contentbased-summary=Models;CollectionFlow;false;AddFieldToList;(System.Collections.Generic.List<System.String>);;Argument[this].SyntheticField[Models.CollectionFlow.tainted];Argument[0].Element;value;df-generated
|
||||
public void AddFieldToList(List<string> input)
|
||||
{
|
||||
input.Add(tainted);
|
||||
}
|
||||
|
||||
// summary=Models;CollectionFlow;false;ReturnFieldInAList;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;CollectionFlow;false;ReturnFieldInAList;();;Argument[this].SyntheticField[Models.CollectionFlow.tainted];ReturnValue.Element;value;df-generated
|
||||
public List<string> ReturnFieldInAList()
|
||||
{
|
||||
return new List<string> { tainted };
|
||||
}
|
||||
|
||||
// summary=Models;CollectionFlow;false;ReturnComplexTypeArray;(System.String[]);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// SPURIOUS-summary=Models;CollectionFlow;false;ReturnComplexTypeArray;(System.String[]);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;CollectionFlow;false;ReturnComplexTypeArray;(System.String[]);;Argument[0];ReturnValue;value;df-generated
|
||||
public string[] ReturnComplexTypeArray(string[] a)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
// summary=Models;CollectionFlow;false;ReturnBulkTypeList;(System.Collections.Generic.List<System.Byte>);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// SPURIOUS-summary=Models;CollectionFlow;false;ReturnBulkTypeList;(System.Collections.Generic.List<System.Byte>);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;CollectionFlow;false;ReturnBulkTypeList;(System.Collections.Generic.List<System.Byte>);;Argument[0];ReturnValue;value;df-generated
|
||||
public List<byte> ReturnBulkTypeList(List<byte> a)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
// summary=Models;CollectionFlow;false;ReturnComplexTypeDictionary;(System.Collections.Generic.Dictionary<System.Int32,System.String>);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// SPURIOUS-summary=Models;CollectionFlow;false;ReturnComplexTypeDictionary;(System.Collections.Generic.Dictionary<System.Int32,System.String>);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;CollectionFlow;false;ReturnComplexTypeDictionary;(System.Collections.Generic.Dictionary<System.Int32,System.String>);;Argument[0];ReturnValue;value;df-generated
|
||||
public Dictionary<int, string> ReturnComplexTypeDictionary(Dictionary<int, string> a)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
// summary=Models;CollectionFlow;false;ReturnUntypedArray;(System.Array);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// SPURIOUS-summary=Models;CollectionFlow;false;ReturnUntypedArray;(System.Array);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;CollectionFlow;false;ReturnUntypedArray;(System.Array);;Argument[0];ReturnValue;value;df-generated
|
||||
public Array ReturnUntypedArray(Array a)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
// summary=Models;CollectionFlow;false;ReturnUntypedList;(System.Collections.IList);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// SPURIOUS-summary=Models;CollectionFlow;false;ReturnUntypedList;(System.Collections.IList);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;CollectionFlow;false;ReturnUntypedList;(System.Collections.IList);;Argument[0];ReturnValue;value;df-generated
|
||||
public IList ReturnUntypedList(IList a)
|
||||
{
|
||||
return a;
|
||||
@@ -159,19 +179,22 @@ public class IEnumerableFlow
|
||||
{
|
||||
private string tainted;
|
||||
|
||||
// summary=Models;IEnumerableFlow;false;ReturnIEnumerable;(System.Collections.Generic.IEnumerable<System.String>);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// SPURIOUS-summary=Models;IEnumerableFlow;false;ReturnIEnumerable;(System.Collections.Generic.IEnumerable<System.String>);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;IEnumerableFlow;false;ReturnIEnumerable;(System.Collections.Generic.IEnumerable<System.String>);;Argument[0];ReturnValue;value;df-generated
|
||||
public IEnumerable<string> ReturnIEnumerable(IEnumerable<string> input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
// summary=Models;IEnumerableFlow;false;ReturnIEnumerableElement;(System.Collections.Generic.IEnumerable<System.Object>);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;IEnumerableFlow;false;ReturnIEnumerableElement;(System.Collections.Generic.IEnumerable<System.Object>);;Argument[0].Element;ReturnValue;value;df-generated
|
||||
public object ReturnIEnumerableElement(IEnumerable<object> input)
|
||||
{
|
||||
return input.First();
|
||||
}
|
||||
|
||||
// summary=Models;IEnumerableFlow;false;ReturnFieldInIEnumerable;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;IEnumerableFlow;false;ReturnFieldInIEnumerable;();;Argument[this].SyntheticField[Models.IEnumerableFlow.tainted];ReturnValue.Element;value;df-generated
|
||||
public IEnumerable<string> ReturnFieldInIEnumerable()
|
||||
{
|
||||
return new List<string> { tainted };
|
||||
@@ -183,42 +206,49 @@ public class GenericFlow<T>
|
||||
private T tainted;
|
||||
|
||||
// summary=Models;GenericFlow<T>;false;SetGenericField;(T);;Argument[0];Argument[this];taint;df-generated
|
||||
// contentbased-summary=Models;GenericFlow<T>;false;SetGenericField;(T);;Argument[0];Argument[this].SyntheticField[Models.GenericFlow`1.tainted];value;df-generated
|
||||
public void SetGenericField(T t)
|
||||
{
|
||||
tainted = t;
|
||||
}
|
||||
|
||||
// summary=Models;GenericFlow<T>;false;ReturnGenericField;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;GenericFlow<T>;false;ReturnGenericField;();;Argument[this].SyntheticField[Models.GenericFlow`1.tainted];ReturnValue;value;df-generated
|
||||
public T ReturnGenericField()
|
||||
{
|
||||
return tainted;
|
||||
}
|
||||
|
||||
// summary=Models;GenericFlow<T>;false;AddFieldToGenericList;(System.Collections.Generic.List<T>);;Argument[this];Argument[0].Element;taint;df-generated
|
||||
// contentbased-summary=Models;GenericFlow<T>;false;AddFieldToGenericList;(System.Collections.Generic.List<T>);;Argument[this].SyntheticField[Models.GenericFlow`1.tainted];Argument[0].Element;value;df-generated
|
||||
public void AddFieldToGenericList(List<T> input)
|
||||
{
|
||||
input.Add(tainted);
|
||||
}
|
||||
|
||||
// summary=Models;GenericFlow<T>;false;ReturnFieldInGenericList;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;GenericFlow<T>;false;ReturnFieldInGenericList;();;Argument[this].SyntheticField[Models.GenericFlow`1.tainted];ReturnValue.Element;value;df-generated
|
||||
public List<T> ReturnFieldInGenericList()
|
||||
{
|
||||
return new List<T> { tainted };
|
||||
}
|
||||
|
||||
// summary=Models;GenericFlow<T>;false;ReturnGenericParam<S>;(S);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;GenericFlow<T>;false;ReturnGenericParam<S>;(S);;Argument[0];ReturnValue;value;df-generated
|
||||
public S ReturnGenericParam<S>(S input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
// summary=Models;GenericFlow<T>;false;ReturnGenericElement<S>;(System.Collections.Generic.List<S>);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;GenericFlow<T>;false;ReturnGenericElement<S>;(System.Collections.Generic.List<S>);;Argument[0].Element;ReturnValue;value;df-generated
|
||||
public S ReturnGenericElement<S>(List<S> input)
|
||||
{
|
||||
return input[0];
|
||||
}
|
||||
|
||||
// summary=Models;GenericFlow<T>;false;AddToGenericList<S>;(System.Collections.Generic.List<S>,S);;Argument[1];Argument[0].Element;taint;df-generated
|
||||
// contentbased-summary=Models;GenericFlow<T>;false;AddToGenericList<S>;(System.Collections.Generic.List<S>,S);;Argument[1];Argument[0].Element;value;df-generated
|
||||
public void AddToGenericList<S>(List<S> input, S data)
|
||||
{
|
||||
input.Add(data);
|
||||
@@ -228,6 +258,7 @@ public class GenericFlow<T>
|
||||
public abstract class BaseClassFlow
|
||||
{
|
||||
// summary=Models;BaseClassFlow;true;ReturnParam;(System.Object);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;BaseClassFlow;true;ReturnParam;(System.Object);;Argument[0];ReturnValue;value;df-generated
|
||||
public virtual object ReturnParam(object input)
|
||||
{
|
||||
return input;
|
||||
@@ -237,6 +268,7 @@ public abstract class BaseClassFlow
|
||||
public class DerivedClass1Flow : BaseClassFlow
|
||||
{
|
||||
// summary=Models;DerivedClass1Flow;false;ReturnParam1;(System.String,System.String);;Argument[1];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;DerivedClass1Flow;false;ReturnParam1;(System.String,System.String);;Argument[1];ReturnValue;value;df-generated
|
||||
public string ReturnParam1(string input0, string input1)
|
||||
{
|
||||
return input1;
|
||||
@@ -246,12 +278,14 @@ public class DerivedClass1Flow : BaseClassFlow
|
||||
public class DerivedClass2Flow : BaseClassFlow
|
||||
{
|
||||
// summary=Models;BaseClassFlow;true;ReturnParam;(System.Object);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;BaseClassFlow;true;ReturnParam;(System.Object);;Argument[0];ReturnValue;value;df-generated
|
||||
public override object ReturnParam(object input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
// summary=Models;DerivedClass2Flow;false;ReturnParam0;(System.String,System.Int32);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;DerivedClass2Flow;false;ReturnParam0;(System.String,System.Int32);;Argument[0];ReturnValue;value;df-generated
|
||||
public string ReturnParam0(string input0, int input1)
|
||||
{
|
||||
return input0;
|
||||
@@ -263,6 +297,7 @@ public class OperatorFlow
|
||||
public readonly object Field;
|
||||
|
||||
// summary=Models;OperatorFlow;false;OperatorFlow;(System.Object);;Argument[0];Argument[this];taint;df-generated
|
||||
// contentbased-summary=Models;OperatorFlow;false;OperatorFlow;(System.Object);;Argument[0];Argument[this].Field[Models.OperatorFlow.Field];value;df-generated
|
||||
public OperatorFlow(object o)
|
||||
{
|
||||
Field = o;
|
||||
@@ -270,6 +305,7 @@ public class OperatorFlow
|
||||
|
||||
// Flow Summary.
|
||||
// summary=Models;OperatorFlow;false;op_Addition;(Models.OperatorFlow,Models.OperatorFlow);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;OperatorFlow;false;op_Addition;(Models.OperatorFlow,Models.OperatorFlow);;Argument[0];ReturnValue;value;df-generated
|
||||
public static OperatorFlow operator +(OperatorFlow a, OperatorFlow b)
|
||||
{
|
||||
return a;
|
||||
@@ -310,6 +346,7 @@ public class EqualsGetHashCodeNoFlow
|
||||
}
|
||||
|
||||
// summary=Models;EqualsGetHashCodeNoFlow;false;Equals;(System.String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;EqualsGetHashCodeNoFlow;false;Equals;(System.String);;Argument[0];ReturnValue;value;df-generated
|
||||
public string Equals(string s)
|
||||
{
|
||||
return s;
|
||||
@@ -327,12 +364,14 @@ public class Properties
|
||||
private string tainted;
|
||||
|
||||
// summary=Models;Properties;false;get_Prop1;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;Properties;false;get_Prop1;();;Argument[this].SyntheticField[Models.Properties.tainted];ReturnValue;value;df-generated
|
||||
public string Prop1
|
||||
{
|
||||
get { return tainted; }
|
||||
}
|
||||
|
||||
// summary=Models;Properties;false;set_Prop2;(System.String);;Argument[0];Argument[this];taint;df-generated
|
||||
// contentbased-summary=Models;Properties;false;set_Prop2;(System.String);;Argument[0];Argument[this].SyntheticField[Models.Properties.tainted];value;df-generated
|
||||
public string Prop2
|
||||
{
|
||||
set { tainted = value; }
|
||||
@@ -513,6 +552,7 @@ public class Inheritance
|
||||
public class AImplBasePublic : BasePublic
|
||||
{
|
||||
// summary=Models;Inheritance+BasePublic;true;Id;(System.String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;Inheritance+BasePublic;true;Id;(System.String);;Argument[0];ReturnValue;value;df-generated
|
||||
public override string Id(string x)
|
||||
{
|
||||
return x;
|
||||
@@ -542,6 +582,7 @@ public class Inheritance
|
||||
public class BImpl : B
|
||||
{
|
||||
// summary=Models;Inheritance+IPublic1;true;Id;(System.String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;Inheritance+IPublic1;true;Id;(System.String);;Argument[0];ReturnValue;value;df-generated
|
||||
public override string Id(string x)
|
||||
{
|
||||
return x;
|
||||
@@ -551,6 +592,7 @@ public class Inheritance
|
||||
private class CImpl : C
|
||||
{
|
||||
// summary=Models;Inheritance+IPublic2;true;Id;(System.String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;Inheritance+IPublic2;true;Id;(System.String);;Argument[0];ReturnValue;value;df-generated
|
||||
public override string Id(string x)
|
||||
{
|
||||
return x;
|
||||
@@ -572,6 +614,7 @@ public class Inheritance
|
||||
private string tainted;
|
||||
|
||||
// summary=Models;Inheritance+IPublic3;true;get_Prop;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;Inheritance+IPublic3;true;get_Prop;();;Argument[this].SyntheticField[Models.Inheritance+DImpl.tainted];ReturnValue;value;df-generated
|
||||
public override string Prop { get { return tainted; } }
|
||||
}
|
||||
}
|
||||
@@ -586,14 +629,54 @@ public class MemberFlow
|
||||
}
|
||||
|
||||
// summary=Models;MemberFlow;false;M1;(Models.MemberFlow+C);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;MemberFlow;false;M1;(Models.MemberFlow+C);;Argument[0].Property[Models.MemberFlow+C.Prop];ReturnValue;value;df-generated
|
||||
public string M1(C c)
|
||||
{
|
||||
return c.Prop;
|
||||
}
|
||||
|
||||
// summary=Models;MemberFlow;false;M2;(Models.MemberFlow+C);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;MemberFlow;false;M2;(Models.MemberFlow+C);;Argument[0].Field[Models.MemberFlow+C.Field];ReturnValue;value;df-generated
|
||||
public string M2(C c)
|
||||
{
|
||||
return c.Field;
|
||||
}
|
||||
}
|
||||
|
||||
public class IDictionaryFlow
|
||||
{
|
||||
// summary=Models;IDictionaryFlow;false;ReturnIDictionaryValue;(System.Collections.Generic.IDictionary<System.Object,System.Object>,System.Object);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;IDictionaryFlow;false;ReturnIDictionaryValue;(System.Collections.Generic.IDictionary<System.Object,System.Object>,System.Object);;Argument[0].Element.Property[System.Collections.Generic.KeyValuePair`2.Value];ReturnValue;value;df-generated
|
||||
public object ReturnIDictionaryValue(IDictionary<object, object> input, object key)
|
||||
{
|
||||
return input[key];
|
||||
}
|
||||
}
|
||||
|
||||
public class NestedFieldFlow
|
||||
{
|
||||
public NestedFieldFlow FieldA;
|
||||
public NestedFieldFlow FieldB;
|
||||
|
||||
// summary=Models;NestedFieldFlow;false;Move;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;NestedFieldFlow;false;Move;();;Argument[this].Field[Models.NestedFieldFlow.FieldA];ReturnValue.Field[Models.NestedFieldFlow.FieldB];value;df-generated
|
||||
public NestedFieldFlow Move()
|
||||
{
|
||||
return new NestedFieldFlow() { FieldB = this.FieldA };
|
||||
}
|
||||
|
||||
// summary=Models;NestedFieldFlow;false;MoveNested;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;NestedFieldFlow;false;MoveNested;();;Argument[this].Field[Models.NestedFieldFlow.FieldB].Field[Models.NestedFieldFlow.FieldA];ReturnValue.Field[Models.NestedFieldFlow.FieldA].Field[Models.NestedFieldFlow.FieldB];value;df-generated
|
||||
public NestedFieldFlow MoveNested()
|
||||
{
|
||||
return new NestedFieldFlow() { FieldA = FieldB.Move() };
|
||||
}
|
||||
|
||||
// summary=Models;NestedFieldFlow;false;ReverseFields;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;NestedFieldFlow;false;ReverseFields;();;Argument[this].Field[Models.NestedFieldFlow.FieldA].Field[Models.NestedFieldFlow.FieldB];ReturnValue.Field[Models.NestedFieldFlow.FieldA].Field[Models.NestedFieldFlow.FieldB];value;df-generated
|
||||
public NestedFieldFlow ReverseFields()
|
||||
{
|
||||
var x = new NestedFieldFlow() { FieldB = this.FieldA.FieldB };
|
||||
return new NestedFieldFlow() { FieldA = x };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
private import java
|
||||
private import DataFlowImplSpecific
|
||||
private import codeql.dataflow.internal.ContentDataFlowImpl
|
||||
|
||||
module ContentDataFlow {
|
||||
import MakeImplContentDataFlow<Location, JavaDataFlow>
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* @name Capture content based summary models.
|
||||
* @description Finds applicable content based summary models to be used by other queries.
|
||||
* @kind diagnostic
|
||||
* @id java/utils/modelgenerator/contentbased-summary-models
|
||||
* @tags modelgenerator
|
||||
*/
|
||||
|
||||
import internal.CaptureModels
|
||||
|
||||
from DataFlowSummaryTargetApi api, string flow
|
||||
where flow = captureContentFlow(api)
|
||||
select flow order by flow
|
||||
@@ -18,17 +18,35 @@ private class ReturnNodeExt extends DataFlow::Node {
|
||||
kind = DataFlowImplCommon::getParamReturnPosition(this, _).getKind()
|
||||
}
|
||||
|
||||
string getOutput() {
|
||||
kind instanceof DataFlowImplCommon::ValueReturnKind and
|
||||
/**
|
||||
* Gets the kind of the return node.
|
||||
*/
|
||||
DataFlowImplCommon::ReturnKindExt getKind() { result = kind }
|
||||
}
|
||||
|
||||
bindingset[c]
|
||||
private signature string printCallableParamSig(Callable c, ParameterPosition p);
|
||||
|
||||
private module PrintReturnNodeExt<printCallableParamSig/2 printCallableParam> {
|
||||
string getOutput(ReturnNodeExt node) {
|
||||
node.getKind() instanceof DataFlowImplCommon::ValueReturnKind and
|
||||
result = "ReturnValue"
|
||||
or
|
||||
exists(ParameterPosition pos |
|
||||
pos = kind.(DataFlowImplCommon::ParamUpdateReturnKind).getPosition() and
|
||||
result = paramReturnNodeAsOutput(returnNodeEnclosingCallable(this), pos)
|
||||
pos = node.getKind().(DataFlowImplCommon::ParamUpdateReturnKind).getPosition() and
|
||||
result = printCallableParam(returnNodeEnclosingCallable(node), pos)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
string getOutput(ReturnNodeExt node) {
|
||||
result = PrintReturnNodeExt<paramReturnNodeAsOutput/2>::getOutput(node)
|
||||
}
|
||||
|
||||
string getContentOutput(ReturnNodeExt node) {
|
||||
result = PrintReturnNodeExt<paramReturnNodeAsContentOutput/2>::getOutput(node)
|
||||
}
|
||||
|
||||
class DataFlowSummaryTargetApi extends SummaryTargetApi {
|
||||
DataFlowSummaryTargetApi() { not isUninterestingForDataFlowModels(this) }
|
||||
}
|
||||
@@ -71,7 +89,8 @@ private predicate isRelevantTaintStep(DataFlow::Node node1, DataFlow::Node node2
|
||||
* Holds if content `c` is either a field, a synthetic field or language specific
|
||||
* content of a relevant type or a container like content.
|
||||
*/
|
||||
private predicate isRelevantContent(DataFlow::ContentSet c) {
|
||||
pragma[nomagic]
|
||||
private predicate isRelevantContent0(DataFlow::ContentSet c) {
|
||||
isRelevantTypeInContent(c) or
|
||||
containerContent(c)
|
||||
}
|
||||
@@ -85,6 +104,16 @@ string parameterNodeAsInput(DataFlow::ParameterNode p) {
|
||||
result = qualifierString() and p instanceof InstanceParameterNode
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MaD string representation of the parameter `p`
|
||||
* when used in content flow.
|
||||
*/
|
||||
string parameterNodeAsContentInput(DataFlow::ParameterNode p) {
|
||||
result = parameterContentAccess(p.asParameter())
|
||||
or
|
||||
result = qualifierString() and p instanceof InstanceParameterNode
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MaD input string representation of `source`.
|
||||
*/
|
||||
@@ -170,7 +199,7 @@ module PropagateFlowConfig implements DataFlow::StateConfigSig {
|
||||
) {
|
||||
exists(DataFlow::ContentSet c |
|
||||
DataFlowImplCommon::store(node1, c.getAStoreContent(), node2, _, _) and
|
||||
isRelevantContent(c) and
|
||||
isRelevantContent0(c) and
|
||||
(
|
||||
state1 instanceof TaintRead and state2.(TaintStore).getStep() = 1
|
||||
or
|
||||
@@ -180,7 +209,7 @@ module PropagateFlowConfig implements DataFlow::StateConfigSig {
|
||||
or
|
||||
exists(DataFlow::ContentSet c |
|
||||
DataFlowPrivate::readStep(node1, c, node2) and
|
||||
isRelevantContent(c) and
|
||||
isRelevantContent0(c) and
|
||||
state1.(TaintRead).getStep() + 1 = state2.(TaintRead).getStep()
|
||||
)
|
||||
}
|
||||
@@ -196,6 +225,9 @@ module PropagateFlowConfig implements DataFlow::StateConfigSig {
|
||||
|
||||
module PropagateFlow = TaintTracking::GlobalWithState<PropagateFlowConfig>;
|
||||
|
||||
/**
|
||||
* Gets the summary model(s) of `api`, if there is flow from parameters to return value or parameter.
|
||||
*/
|
||||
string captureThroughFlow0(
|
||||
DataFlowSummaryTargetApi api, DataFlow::ParameterNode p, ReturnNodeExt returnNodeExt
|
||||
) {
|
||||
@@ -203,7 +235,7 @@ string captureThroughFlow0(
|
||||
p.getEnclosingCallable() = api and
|
||||
returnNodeExt.(DataFlow::Node).getEnclosingCallable() = api and
|
||||
input = parameterNodeAsInput(p) and
|
||||
output = returnNodeExt.getOutput() and
|
||||
output = getOutput(returnNodeExt) and
|
||||
input != output and
|
||||
result = Printing::asTaintModel(api, input, output)
|
||||
)
|
||||
@@ -219,6 +251,69 @@ string captureThroughFlow(DataFlowSummaryTargetApi api) {
|
||||
)
|
||||
}
|
||||
|
||||
private module PropagateContentFlowConfig implements ContentDataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
source instanceof DataFlow::ParameterNode and
|
||||
source.getEnclosingCallable() instanceof DataFlowSummaryTargetApi
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
sink instanceof ReturnNodeExt and
|
||||
sink.getEnclosingCallable() instanceof DataFlowSummaryTargetApi
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep = isAdditionalContentFlowStep/2;
|
||||
|
||||
predicate isBarrier(DataFlow::Node n) {
|
||||
exists(Type t | t = n.getType() and not isRelevantType(t))
|
||||
}
|
||||
|
||||
int accessPathLimit() { result = 2 }
|
||||
|
||||
predicate isRelevantContent(DataFlow::ContentSet s) { isRelevantContent0(s) }
|
||||
|
||||
DataFlow::FlowFeature getAFeature() {
|
||||
result instanceof DataFlow::FeatureEqualSourceSinkCallContext
|
||||
}
|
||||
}
|
||||
|
||||
private module PropagateContentFlow = ContentDataFlow::Global<PropagateContentFlowConfig>;
|
||||
|
||||
private string getContent(PropagateContentFlow::AccessPath ap, int i) {
|
||||
exists(ContentSet head, PropagateContentFlow::AccessPath tail |
|
||||
head = ap.getHead() and
|
||||
tail = ap.getTail()
|
||||
|
|
||||
i = 0 and
|
||||
result = "." + printContent(head)
|
||||
or
|
||||
i > 0 and result = getContent(tail, i - 1)
|
||||
)
|
||||
}
|
||||
|
||||
private string printStoreAccessPath(PropagateContentFlow::AccessPath ap) {
|
||||
result = concat(int i | | getContent(ap, i), "" order by i)
|
||||
}
|
||||
|
||||
private string printReadAccessPath(PropagateContentFlow::AccessPath ap) {
|
||||
result = concat(int i | | getContent(ap, i), "" order by i desc)
|
||||
}
|
||||
|
||||
string captureContentFlow(DataFlowSummaryTargetApi api) {
|
||||
exists(
|
||||
DataFlow::ParameterNode p, ReturnNodeExt returnNodeExt, string input, string output,
|
||||
PropagateContentFlow::AccessPath reads, PropagateContentFlow::AccessPath stores,
|
||||
boolean preservesValue
|
||||
|
|
||||
PropagateContentFlow::flow(p, reads, returnNodeExt, stores, preservesValue) and
|
||||
returnNodeExt.getEnclosingCallable() = api and
|
||||
input = parameterNodeAsContentInput(p) + printReadAccessPath(reads) and
|
||||
output = getContentOutput(returnNodeExt) + printStoreAccessPath(stores) and
|
||||
input != output and
|
||||
result = Printing::asModel(api, input, output, preservesValue)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A dataflow configuration used for finding new sources.
|
||||
* The sources are the already known existing sources and the sinks are the API return nodes.
|
||||
@@ -261,7 +356,7 @@ string captureSource(DataFlowSourceTargetApi api) {
|
||||
ExternalFlow::sourceNode(source, kind) and
|
||||
api = sink.getEnclosingCallable() and
|
||||
not irrelevantSourceSinkApi(source.getEnclosingCallable(), api) and
|
||||
result = Printing::asSourceModel(api, sink.getOutput(), kind)
|
||||
result = Printing::asSourceModel(api, getOutput(sink), kind)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
|
||||
private import java as J
|
||||
private import semmle.code.java.dataflow.internal.DataFlowPrivate
|
||||
private import semmle.code.java.dataflow.internal.DataFlowUtil as DataFlowUtil
|
||||
private import semmle.code.java.dataflow.internal.ContainerFlow as ContainerFlow
|
||||
private import semmle.code.java.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
|
||||
private import semmle.code.java.dataflow.internal.ModelExclusions
|
||||
private import semmle.code.java.dataflow.DataFlow as Df
|
||||
private import semmle.code.java.dataflow.internal.ContentDataFlow as Cdf
|
||||
private import semmle.code.java.dataflow.SSA as Ssa
|
||||
private import semmle.code.java.dataflow.TaintTracking as Tt
|
||||
import semmle.code.java.dataflow.ExternalFlow as ExternalFlow
|
||||
@@ -17,6 +19,8 @@ import semmle.code.java.dataflow.internal.DataFlowDispatch as DataFlowDispatch
|
||||
|
||||
module DataFlow = Df::DataFlow;
|
||||
|
||||
module ContentDataFlow = Cdf::ContentDataFlow;
|
||||
|
||||
module TaintTracking = Tt::TaintTracking;
|
||||
|
||||
class Type = J::Type;
|
||||
@@ -25,6 +29,8 @@ class Unit = J::Unit;
|
||||
|
||||
class Callable = J::Callable;
|
||||
|
||||
class ContentSet = DataFlowUtil::ContentSet;
|
||||
|
||||
private predicate isInfrequentlyUsed(J::CompilationUnit cu) {
|
||||
cu.getPackage().getName().matches("javax.swing%") or
|
||||
cu.getPackage().getName().matches("java.awt%")
|
||||
@@ -217,6 +223,12 @@ string parameterAccess(J::Parameter p) {
|
||||
else result = "Argument[" + p.getPosition() + "]"
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MaD string representation of the parameter `p`
|
||||
* when used in content flow.
|
||||
*/
|
||||
string parameterContentAccess(J::Parameter p) { result = "Argument[" + p.getPosition() + "]" }
|
||||
|
||||
class InstanceParameterNode = DataFlow::InstanceParameterNode;
|
||||
|
||||
class ParameterPosition = DataFlowDispatch::ParameterPosition;
|
||||
@@ -232,6 +244,17 @@ string paramReturnNodeAsOutput(Callable c, ParameterPosition pos) {
|
||||
result = qualifierString() and pos = -1
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MaD string representation of return through parameter at position
|
||||
* `pos` of callable `c` for content flow.
|
||||
*/
|
||||
bindingset[c]
|
||||
string paramReturnNodeAsContentOutput(Callable c, ParameterPosition pos) {
|
||||
result = parameterContentAccess(c.getParameter(pos))
|
||||
or
|
||||
result = qualifierString() and pos = -1
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the enclosing callable of `ret`.
|
||||
*/
|
||||
@@ -305,3 +328,34 @@ bindingset[kind]
|
||||
predicate isRelevantSourceKind(string kind) { any() }
|
||||
|
||||
predicate containerContent = DataFlowPrivate::containerContent/1;
|
||||
|
||||
/**
|
||||
* Holds if there is a taint step from `node1` to `node2` in content flow.
|
||||
*/
|
||||
predicate isAdditionalContentFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
TaintTracking::defaultAdditionalTaintStep(node1, node2, _) and
|
||||
not exists(DataFlow::Content f |
|
||||
DataFlowPrivate::readStep(node1, f, node2) and containerContent(f)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MaD string representation of the contentset `c`.
|
||||
*/
|
||||
string printContent(ContentSet c) {
|
||||
exists(Field f, string name |
|
||||
f = c.(DataFlowUtil::FieldContent).getField() and name = f.getQualifiedName()
|
||||
|
|
||||
if f.isPublic() then result = "Field[" + name + "]" else result = "SyntheticField[" + name + "]"
|
||||
)
|
||||
or
|
||||
result = "SyntheticField[" + c.(DataFlowUtil::SyntheticFieldContent).getField() + "]"
|
||||
or
|
||||
c instanceof DataFlowUtil::CollectionContent and result = "Element"
|
||||
or
|
||||
c instanceof DataFlowUtil::ArrayContent and result = "ArrayElement"
|
||||
or
|
||||
c instanceof DataFlowUtil::MapValueContent and result = "MapValue"
|
||||
or
|
||||
c instanceof DataFlowUtil::MapKeyContent and result = "MapKey"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
unexpectedModel
|
||||
expectedModel
|
||||
@@ -0,0 +1,11 @@
|
||||
import java
|
||||
import utils.modelgenerator.internal.CaptureModels
|
||||
import TestUtilities.InlineMadTest
|
||||
|
||||
module InlineMadTestConfig implements InlineMadTestConfigSig {
|
||||
string getCapturedModel(Callable c) { result = captureContentFlow(c) }
|
||||
|
||||
string getKind() { result = "contentbased-summary" }
|
||||
}
|
||||
|
||||
import InlineMadTest<InlineMadTestConfig>
|
||||
@@ -2,16 +2,18 @@ package p;
|
||||
|
||||
public final class Factory {
|
||||
|
||||
private String value;
|
||||
public String value;
|
||||
|
||||
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
|
||||
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
|
||||
public static Factory create(String value) {
|
||||
return new Factory(value, 0);
|
||||
}
|
||||
@@ -22,6 +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
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -5,6 +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
|
||||
public String returnsInput(String input) {
|
||||
return input;
|
||||
}
|
||||
|
||||
@@ -3,6 +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
|
||||
public FluentAPI returnsThis(String input) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -7,12 +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
|
||||
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
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
@@ -24,6 +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
|
||||
public String or(String defaultValue) {
|
||||
return value != null ? value : defaultValue;
|
||||
}
|
||||
|
||||
@@ -11,6 +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
|
||||
@Override
|
||||
public String id(String s) {
|
||||
return s;
|
||||
@@ -19,6 +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
|
||||
@Override
|
||||
public String id(String s) {
|
||||
return s;
|
||||
@@ -59,6 +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
|
||||
@Override
|
||||
public String id(String s) {
|
||||
return s;
|
||||
@@ -67,6 +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
|
||||
@Override
|
||||
public String id(String s) {
|
||||
return s;
|
||||
@@ -75,6 +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
|
||||
@Override
|
||||
public String id(String s) {
|
||||
return s;
|
||||
@@ -83,6 +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
|
||||
@Override
|
||||
public String id(String s) {
|
||||
return s;
|
||||
|
||||
@@ -10,12 +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
|
||||
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
|
||||
public String yes(String input) {
|
||||
return input;
|
||||
}
|
||||
|
||||
@@ -19,21 +19,25 @@ 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
|
||||
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
|
||||
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
|
||||
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.context].SyntheticField[p.InnerHolder$Context.value];ReturnValue;value;df-generated
|
||||
public String getValue() {
|
||||
return context.getValue();
|
||||
}
|
||||
|
||||
@@ -13,6 +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
|
||||
public Joiner(CharSequence delimiter) {
|
||||
this(delimiter, "", "");
|
||||
}
|
||||
@@ -20,6 +21,9 @@ 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[1];Argument[this].SyntheticField[p.Joiner.prefix];taint;df-generated
|
||||
// contentbased-summary=p;Joiner;false;Joiner;(CharSequence,CharSequence,CharSequence);;Argument[2];Argument[this].SyntheticField[p.Joiner.suffix];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");
|
||||
@@ -32,6 +36,9 @@ 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
|
||||
// contentbased-summary=p;Joiner;false;setEmptyValue;(CharSequence);;Argument[0];Argument[this].SyntheticField[p.Joiner.emptyValue];taint;df-generated
|
||||
// contentbased-summary=p;Joiner;false;setEmptyValue;(CharSequence);;Argument[0];ReturnValue.SyntheticField[p.Joiner.emptyValue];taint;df-generated
|
||||
// contentbased-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();
|
||||
@@ -71,6 +78,8 @@ 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].SyntheticField[p.Joiner.elts].ArrayElement;ReturnValue.SyntheticField[p.Joiner.elts].ArrayElement;value;df-generated
|
||||
// contentbased-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) {
|
||||
@@ -94,6 +103,8 @@ 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].SyntheticField[p.Joiner.elts].ArrayElement;ReturnValue.SyntheticField[p.Joiner.elts].ArrayElement;value;df-generated
|
||||
// contentbased-summary=p;Joiner;false;merge;(Joiner);;Argument[this];ReturnValue;value;df-generated
|
||||
public Joiner merge(Joiner other) {
|
||||
Objects.requireNonNull(other);
|
||||
if (other.elts == null) {
|
||||
|
||||
@@ -17,6 +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
|
||||
public Object m(Object value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -10,6 +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
|
||||
public String doSomething(String value) {
|
||||
return value;
|
||||
}
|
||||
@@ -29,12 +30,18 @@ public class MultipleImpls {
|
||||
private String foo;
|
||||
|
||||
// summary=p;MultipleImpls$Strategy;true;doSomething;(String);;Argument[0];Argument[this];taint;df-generated
|
||||
// A field based model should not be lifted if the field pertains to the concrete
|
||||
// implementation.
|
||||
// SPURIOUS-contentbased-summary=p;MultipleImpls$Strategy;true;doSomething;(String);;Argument[0];Argument[this].SyntheticField[p.MultipleImpls$Strat2.foo];value;df-generated
|
||||
public String doSomething(String value) {
|
||||
this.foo = value;
|
||||
return "none";
|
||||
}
|
||||
|
||||
// summary=p;MultipleImpls$Strat2;true;getValue;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// A field based model should not be lifted if the field pertains to the concrete
|
||||
// implementation.
|
||||
// SPURIOUS-contentbased-summary=p;MultipleImpls$Strat2;true;getValue;();;Argument[this].SyntheticField[p.MultipleImpls$Strat2.foo];ReturnValue;value;df-generated
|
||||
public String getValue() {
|
||||
return this.foo;
|
||||
}
|
||||
|
||||
@@ -8,6 +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
|
||||
public String returnsInput(String input) {
|
||||
return input;
|
||||
}
|
||||
@@ -19,6 +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
|
||||
public String returnMultipleParameters(String one, String two) {
|
||||
if (System.currentTimeMillis() > 100) {
|
||||
return two;
|
||||
@@ -27,26 +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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
public String returnIterableElement(Iterable<String> input) {
|
||||
return input.iterator().next();
|
||||
}
|
||||
@@ -57,16 +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
|
||||
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
|
||||
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
|
||||
public void addTo(String data, List<String> target) {
|
||||
target.add(data);
|
||||
}
|
||||
|
||||
@@ -24,18 +24,20 @@ public final class Pojo {
|
||||
|
||||
private int intValue = 2;
|
||||
|
||||
private byte[] byteArray = new byte[] {1, 2, 3};
|
||||
public 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<Character> charList = Arrays.asList('a', 'b', 'c');
|
||||
private Byte[] byteObjectArray = new Byte[] {1, 2, 3};
|
||||
|
||||
// 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
|
||||
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
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
@@ -62,11 +64,13 @@ 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
|
||||
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
|
||||
public byte[] getByteArray() {
|
||||
return byteArray;
|
||||
}
|
||||
@@ -87,11 +91,13 @@ public final class Pojo {
|
||||
}
|
||||
|
||||
// summary=p;Pojo;false;getBoxedChars;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Pojo;false;getBoxedChars;();;Argument[this].SyntheticField[p.Pojo.charList];ReturnValue;value;df-generated
|
||||
public List<Character> getBoxedChars() {
|
||||
return charList;
|
||||
}
|
||||
|
||||
// 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
|
||||
public Byte[] getBoxedBytes() {
|
||||
return byteObjectArray;
|
||||
}
|
||||
@@ -107,6 +113,7 @@ 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
|
||||
public void fillIn(List<String> target) {
|
||||
target.add(value);
|
||||
}
|
||||
|
||||
@@ -29,6 +29,9 @@ public class PrivateFlowViaPublicInterface {
|
||||
}
|
||||
|
||||
// summary=p;PrivateFlowViaPublicInterface$SPI;true;openStream;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// A field based model should not be lifted if the field pertains to the concrete
|
||||
// implementation.
|
||||
// SPURIOUS-contentbased-summary=p;PrivateFlowViaPublicInterface$SPI;true;openStream;();;Argument[this].SyntheticField[p.PrivateFlowViaPublicInterface$PrivateImplWithSink.file];ReturnValue;taint;df-generated
|
||||
@Override
|
||||
public OutputStream openStream() throws IOException {
|
||||
return new FileOutputStream(file);
|
||||
@@ -51,6 +54,9 @@ public class PrivateFlowViaPublicInterface {
|
||||
}
|
||||
|
||||
// summary=p;PrivateFlowViaPublicInterface;true;createAnSPI;(File);;Argument[0];ReturnValue;taint;df-generated
|
||||
// A field based model should not be lifted if the field pertains to the concrete
|
||||
// implementation.
|
||||
// SPURIOUS-contentbased-summary=p;PrivateFlowViaPublicInterface;true;createAnSPI;(File);;Argument[0];ReturnValue.SyntheticField[p.PrivateFlowViaPublicInterface$PrivateImplWithSink.file];value;df-generated
|
||||
public static SPI createAnSPI(File file) {
|
||||
return new PrivateImplWithSink(file);
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ class Generator:
|
||||
self.generateSources = False
|
||||
self.generateSummaries = False
|
||||
self.generateNeutrals = False
|
||||
self.generateContentSummaries = False
|
||||
self.generateTypeBasedSummaries = False
|
||||
self.dryRun = False
|
||||
self.dirname = "modelgenerator"
|
||||
@@ -50,6 +51,7 @@ Which models are generated is controlled by the flags:
|
||||
--with-sources
|
||||
--with-summaries
|
||||
--with-neutrals
|
||||
--with-content-summaries (Experimental). May not be used in conjunction with --with-summaries
|
||||
--with-typebased-summaries (Experimental)
|
||||
If none of these flags are specified, all models are generated except for the type based models.
|
||||
|
||||
@@ -81,6 +83,10 @@ Requirements: `codeql` should both appear on your path.
|
||||
generator.printHelp()
|
||||
sys.exit(0)
|
||||
|
||||
if "--with-summaries" in sys.argv and "--with-content-summaries" in sys.argv:
|
||||
generator.printHelp()
|
||||
sys.exit(0)
|
||||
|
||||
if "--with-sinks" in sys.argv:
|
||||
sys.argv.remove("--with-sinks")
|
||||
generator.generateSinks = True
|
||||
@@ -97,6 +103,10 @@ Requirements: `codeql` should both appear on your path.
|
||||
sys.argv.remove("--with-neutrals")
|
||||
generator.generateNeutrals = True
|
||||
|
||||
if "--with-content-summaries" in sys.argv:
|
||||
sys.argv.remove("--with-content-summaries")
|
||||
generator.generateContentSummaries = True
|
||||
|
||||
if "--with-typebased-summaries" in sys.argv:
|
||||
sys.argv.remove("--with-typebased-summaries")
|
||||
generator.generateTypeBasedSummaries = True
|
||||
@@ -105,7 +115,7 @@ Requirements: `codeql` should both appear on your path.
|
||||
sys.argv.remove("--dry-run")
|
||||
generator.dryRun = True
|
||||
|
||||
if not generator.generateSinks and not generator.generateSources and not generator.generateSummaries and not generator.generateNeutrals and not generator.generateTypeBasedSummaries:
|
||||
if not generator.generateSinks and not generator.generateSources and not generator.generateSummaries and not generator.generateNeutrals and not generator.generateTypeBasedSummaries and not generator.generateContentSummaries:
|
||||
generator.generateSinks = generator.generateSources = generator.generateSummaries = generator.generateNeutrals = True
|
||||
|
||||
n = len(sys.argv)
|
||||
@@ -162,8 +172,13 @@ Requirements: `codeql` should both appear on your path.
|
||||
neutralAddsTo = self.getAddsTo("CaptureNeutralModels.ql", helpers.neutralModelPredicate)
|
||||
else:
|
||||
neutralAddsTo = { }
|
||||
|
||||
return helpers.merge(summaryAddsTo, sinkAddsTo, sourceAddsTo, neutralAddsTo)
|
||||
|
||||
if self.generateContentSummaries:
|
||||
contentSummaryAddsTo = self.getAddsTo("CaptureContentSummaryModels.ql", helpers.summaryModelPredicate)
|
||||
else:
|
||||
contentSummaryAddsTo = { }
|
||||
|
||||
return helpers.merge(summaryAddsTo, contentSummaryAddsTo, sinkAddsTo, sourceAddsTo, neutralAddsTo)
|
||||
|
||||
def makeTypeBasedContent(self):
|
||||
if self.generateTypeBasedSummaries:
|
||||
|
||||
@@ -97,6 +97,18 @@ module ModelPrintingImpl<ModelPrintingLangSig Lang> {
|
||||
result = asSummaryModel(api, input, output, "taint")
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the summary model for `api` with `input` and `output`.
|
||||
*/
|
||||
bindingset[input, output, preservesValue]
|
||||
string asModel(Printing::SummaryApi api, string input, string output, boolean preservesValue) {
|
||||
preservesValue = true and
|
||||
result = asValueModel(api, input, output)
|
||||
or
|
||||
preservesValue = false and
|
||||
result = asTaintModel(api, input, output)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the sink model for `api` with `input` and `kind`.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user