Merge pull request #13432 from michaelnebel/updateissupported

Java/C#: Update telemetry queries to report callables with sink/source neutrals as being supported.
This commit is contained in:
Michael Nebel
2023-08-22 08:39:38 +02:00
committed by GitHub
24 changed files with 30266 additions and 30087 deletions

View File

@@ -296,11 +296,21 @@ module Public {
predicate hasProvenance(Provenance provenance) { provenance = "manual" }
}
/** A callable where there is no flow via the callable. */
class NeutralCallable extends SummarizedCallableBase {
/**
* A callable where there is no flow via the callable.
*/
class NeutralSummaryCallable extends NeutralCallable {
NeutralSummaryCallable() { this.getKind() = "summary" }
}
/**
* A callable that has a neutral model.
*/
class NeutralCallable extends NeutralCallableBase {
private string kind;
private Provenance provenance;
NeutralCallable() { neutralSummaryElement(this, provenance) }
NeutralCallable() { neutralElement(this, kind, provenance) }
/**
* Holds if the neutral is auto generated.
@@ -316,6 +326,11 @@ module Public {
* Holds if the neutral has provenance `p`.
*/
predicate hasProvenance(Provenance p) { p = provenance }
/**
* Gets the kind of the neutral.
*/
string getKind() { result = kind }
}
}
@@ -1318,6 +1333,11 @@ module Private {
/** Gets the string representation of this callable used by `neutral/1`. */
abstract string getCallableCsv();
/**
* Gets the kind of the neutral.
*/
string getKind() { result = super.getKind() }
string toString() { result = super.toString() }
}
@@ -1358,12 +1378,13 @@ module Private {
/**
* Holds if a neutral model `csv` exists (semi-colon separated format). Used for testing purposes.
* The syntax is: "namespace;type;name;signature;provenance"",
* The syntax is: "namespace;type;name;signature;kind;provenance"",
*/
query predicate neutral(string csv) {
exists(RelevantNeutralCallable c |
csv =
c.getCallableCsv() // Callable information
+ c.getKind() + ";" // kind
+ renderProvenanceNeutral(c) // provenance
)
}

View File

@@ -15,9 +15,15 @@ private import semmle.code.csharp.Unification
private import semmle.code.csharp.dataflow.ExternalFlow
private import semmle.code.csharp.dataflow.FlowSummary as FlowSummary
class SummarizedCallableBase extends Callable {
SummarizedCallableBase() { this.isUnboundDeclaration() }
}
/**
* A class of callables that are candidates for flow summary modeling.
*/
class SummarizedCallableBase = UnboundCallable;
/**
* A class of callables that are candidates for neutral modeling.
*/
class NeutralCallableBase = UnboundCallable;
/**
* A module for importing frameworks that define synthetic globals.
@@ -120,12 +126,12 @@ predicate summaryElement(Callable c, string input, string output, string kind, s
}
/**
* Holds if a neutral summary model exists for `c` with provenance `provenace`,
* which means that there is no flow through `c`.
* Holds if a neutral model exists for `c` of kind `kind`
* and with provenance `provenance`.
*/
predicate neutralSummaryElement(Callable c, string provenance) {
predicate neutralElement(Callable c, string kind, string provenance) {
exists(string namespace, string type, string name, string signature |
neutralModel(namespace, type, name, signature, "summary", provenance) and
neutralModel(namespace, type, name, signature, kind, provenance) and
c = interpretElement(namespace, type, false, name, signature, "")
)
}

View File

@@ -6,7 +6,7 @@ private class IncludeAllSummarizedCallable extends IncludeSummarizedCallable {
IncludeAllSummarizedCallable() { exists(this) }
}
private class IncludeNeutralCallable extends RelevantNeutralCallable instanceof FlowSummaryImpl::Public::NeutralCallable
private class IncludeNeutralSummarizedCallable extends RelevantNeutralCallable instanceof FlowSummaryImpl::Public::NeutralSummaryCallable
{
/** Gets a string representing the callable in semi-colon separated format for use in flow summaries. */
final override string getCallableCsv() { result = Csv::asPartialNeutralModel(this) }

View File

@@ -15,19 +15,19 @@ public class SupportedExternalApis
public void M2()
{
var d0 = new DateTime(); // Uninteresting parameterless constructor
var next0 = d0.AddYears(30); // Has no flow summary, supported as negative summary
var next0 = d0.AddYears(30); // Has no flow summary, supported as neutral summary model
var d1 = new DateTime(2000, 1, 1); // Interesting constructor, supported as negative summary
var next1 = next0.AddDays(3); // Has no flow summary, supported as negative summary
var next2 = next1.AddYears(5); // Has no flow summary, supported as negative summary
var d1 = new DateTime(2000, 1, 1); // Interesting constructor, supported as neutral summary model
var next1 = next0.AddDays(3); // Has no flow summary, supported as neutral summary model
var next2 = next1.AddYears(5); // Has no flow summary, supported as neutral summary model
}
public void M3()
{
var guid1 = Guid.Parse("{12345678-1234-1234-1234-123456789012}"); // Has no flow summary, supported as negative summary
var guid1 = Guid.Parse("{12345678-1234-1234-1234-123456789012}"); // Has no flow summary, supported as neutral summary model
}
public void M4()
public void M4()
{
var o = new object(); // Uninteresting parameterless constructor
var response = new HttpResponse(); // Uninteresting parameterless constructor
@@ -38,11 +38,11 @@ public class SupportedExternalApis
response.Write(o); // Known sink
}
public void M5()
public void M5()
{
var l1 = Console.ReadLine(); // Known source
var l2 = Console.ReadLine(); // Known source
Console.SetError(Console.Out); // Has no flow summary, supported as negative summary
Console.SetError(Console.Out); // Has no flow summary, supported as neutral summary model
var x = Console.Read(); // Known source
}
}

View File

@@ -296,11 +296,21 @@ module Public {
predicate hasProvenance(Provenance provenance) { provenance = "manual" }
}
/** A callable where there is no flow via the callable. */
class NeutralCallable extends SummarizedCallableBase {
/**
* A callable where there is no flow via the callable.
*/
class NeutralSummaryCallable extends NeutralCallable {
NeutralSummaryCallable() { this.getKind() = "summary" }
}
/**
* A callable that has a neutral model.
*/
class NeutralCallable extends NeutralCallableBase {
private string kind;
private Provenance provenance;
NeutralCallable() { neutralSummaryElement(this, provenance) }
NeutralCallable() { neutralElement(this, kind, provenance) }
/**
* Holds if the neutral is auto generated.
@@ -316,6 +326,11 @@ module Public {
* Holds if the neutral has provenance `p`.
*/
predicate hasProvenance(Provenance p) { p = provenance }
/**
* Gets the kind of the neutral.
*/
string getKind() { result = kind }
}
}
@@ -1318,6 +1333,11 @@ module Private {
/** Gets the string representation of this callable used by `neutral/1`. */
abstract string getCallableCsv();
/**
* Gets the kind of the neutral.
*/
string getKind() { result = super.getKind() }
string toString() { result = super.toString() }
}
@@ -1358,12 +1378,13 @@ module Private {
/**
* Holds if a neutral model `csv` exists (semi-colon separated format). Used for testing purposes.
* The syntax is: "namespace;type;name;signature;provenance"",
* The syntax is: "namespace;type;name;signature;kind;provenance"",
*/
query predicate neutral(string csv) {
exists(RelevantNeutralCallable c |
csv =
c.getCallableCsv() // Callable information
+ c.getKind() + ";" // kind
+ renderProvenanceNeutral(c) // provenance
)
}

View File

@@ -15,8 +15,16 @@ private module FlowSummaries {
private import semmle.go.dataflow.FlowSummary as F
}
/**
* A class of callables that are candidates for flow summary modeling.
*/
class SummarizedCallableBase = Callable;
/**
* A class of callables that are candidates for neutral modeling.
*/
class NeutralCallableBase = Callable;
DataFlowCallable inject(SummarizedCallable c) { result.asSummarizedCallable() = c or none() }
/** Gets the parameter position of the instance parameter. */
@@ -73,11 +81,11 @@ predicate summaryElement(
}
/**
* Holds if a neutral summary model exists for `c` with provenance `provenance`,
* which means that there is no flow through `c`.
* Holds if a neutral model exists for `c` of kind `kind`
* and with provenance `provenance`.
* Note. Neutral models have not been implemented for Go.
*/
predicate neutralSummaryElement(SummarizedCallable c, string provenance) { none() }
predicate neutralElement(NeutralCallableBase c, string kind, string provenance) { none() }
/** Gets the summary component for specification component `c`, if any. */
bindingset[c]

View File

@@ -175,8 +175,6 @@ class Provenance = Impl::Public::Provenance;
class SummarizedCallable = Impl::Public::SummarizedCallable;
class NeutralCallable = Impl::Public::NeutralCallable;
/**
* An adapter class to add the flow summaries specified on `SyntheticCallable`
* to `SummarizedCallable`.

View File

@@ -2,16 +2,16 @@ private import java
private import DataFlowPrivate
private import DataFlowUtil
private import semmle.code.java.dataflow.InstanceAccess
private import semmle.code.java.dataflow.FlowSummary
private import semmle.code.java.dataflow.internal.FlowSummaryImpl as Impl
private import semmle.code.java.dispatch.VirtualDispatch as VirtualDispatch
private import semmle.code.java.dataflow.TypeFlow
private import semmle.code.java.dispatch.internal.Unification
private module DispatchImpl {
private predicate hasHighConfidenceTarget(Call c) {
exists(SummarizedCallable sc | sc.getACall() = c and not sc.applyGeneratedModel())
exists(Impl::Public::SummarizedCallable sc | sc.getACall() = c and not sc.applyGeneratedModel())
or
exists(NeutralCallable nc | nc.getACall() = c and nc.hasManualModel())
exists(Impl::Public::NeutralSummaryCallable nc | nc.getACall() = c and nc.hasManualModel())
or
exists(Callable srcTgt |
srcTgt = VirtualDispatch::viableCallable(c) and

View File

@@ -296,11 +296,21 @@ module Public {
predicate hasProvenance(Provenance provenance) { provenance = "manual" }
}
/** A callable where there is no flow via the callable. */
class NeutralCallable extends SummarizedCallableBase {
/**
* A callable where there is no flow via the callable.
*/
class NeutralSummaryCallable extends NeutralCallable {
NeutralSummaryCallable() { this.getKind() = "summary" }
}
/**
* A callable that has a neutral model.
*/
class NeutralCallable extends NeutralCallableBase {
private string kind;
private Provenance provenance;
NeutralCallable() { neutralSummaryElement(this, provenance) }
NeutralCallable() { neutralElement(this, kind, provenance) }
/**
* Holds if the neutral is auto generated.
@@ -316,6 +326,11 @@ module Public {
* Holds if the neutral has provenance `p`.
*/
predicate hasProvenance(Provenance p) { p = provenance }
/**
* Gets the kind of the neutral.
*/
string getKind() { result = kind }
}
}
@@ -1318,6 +1333,11 @@ module Private {
/** Gets the string representation of this callable used by `neutral/1`. */
abstract string getCallableCsv();
/**
* Gets the kind of the neutral.
*/
string getKind() { result = super.getKind() }
string toString() { result = super.toString() }
}
@@ -1358,12 +1378,13 @@ module Private {
/**
* Holds if a neutral model `csv` exists (semi-colon separated format). Used for testing purposes.
* The syntax is: "namespace;type;name;signature;provenance"",
* The syntax is: "namespace;type;name;signature;kind;provenance"",
*/
query predicate neutral(string csv) {
exists(RelevantNeutralCallable c |
csv =
c.getCallableCsv() // Callable information
+ c.getKind() + ";" // kind
+ renderProvenanceNeutral(c) // provenance
)
}

View File

@@ -14,6 +14,16 @@ private import semmle.code.java.dataflow.internal.AccessPathSyntax as AccessPath
class SummarizedCallableBase = FlowSummary::SummarizedCallableBase;
/**
* A class of callables that are candidates for neutral modeling.
*/
class NeutralCallableBase extends Callable {
NeutralCallableBase() { this.isSourceDeclaration() }
/** Gets a call that targets this neutral. */
Call getACall() { result.getCallee().getSourceDeclaration() = this }
}
/**
* A module for importing frameworks that define synthetic globals.
*/
@@ -156,13 +166,13 @@ predicate summaryElement(
}
/**
* Holds if a neutral summary model exists for `c` with provenance `provenance`,
* which means that there is no flow through `c`.
* Holds if a neutral model exists for `c` of kind `kind`
* and with provenance `provenance`.
*/
predicate neutralSummaryElement(SummarizedCallableBase c, string provenance) {
predicate neutralElement(NeutralCallableBase c, string kind, string provenance) {
exists(string namespace, string type, string name, string signature |
neutralModel(namespace, type, name, signature, "summary", provenance) and
c.asCallable() = interpretElement(namespace, type, false, name, signature, "")
neutralModel(namespace, type, name, signature, kind, provenance) and
c = interpretElement(namespace, type, false, name, signature, "")
)
}

View File

@@ -45,12 +45,10 @@ private int getNumApis(string package, string apiSubset) {
/** Holds if the given `callable` belongs to the specified `apiSubset`. */
private predicate callableSubset(Callable callable, string apiSubset) {
apiSubset in ["topJdkApis", "allApis"] and
(
if apiSubset = "topJdkApis"
then exists(TopJdkApi topJdkApi | callable = topJdkApi.asCallable())
else apiSubset = "allApis"
)
apiSubset = "topJdkApis" and
callable instanceof TopJdkApi
or
apiSubset = "allApis"
}
/**

View File

@@ -1,7 +1,6 @@
/** Provides classes and predicates for working with Top JDK APIs. */
import java
private import semmle.code.java.dataflow.FlowSummary
private import semmle.code.java.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
private import semmle.code.java.dataflow.ExternalFlow
@@ -287,24 +286,29 @@ predicate hasApiName(Callable c, string apiName) {
}
/** A top JDK API. */
class TopJdkApi extends SummarizedCallableBase {
class TopJdkApi extends Callable {
TopJdkApi() {
this.isSourceDeclaration() and
exists(string apiName |
hasApiName(this.asCallable(), apiName) and
hasApiName(this, apiName) and
topJdkApiName(apiName)
)
}
/** Holds if this API has a manual summary model. */
private predicate hasManualSummary() { this.(SummarizedCallable).hasManualModel() }
private predicate hasManualSummary() {
exists(FlowSummaryImpl::Public::SummarizedCallable sc |
sc.asCallable() = this and sc.hasManualModel()
)
}
/** Holds if this API has a manual neutral model. */
private predicate hasManualNeutral() {
this.(FlowSummaryImpl::Public::NeutralCallable).hasManualModel()
/** Holds if this API has a manual neutral summary model. */
private predicate hasManualNeutralSummary() {
this.(FlowSummaryImpl::Public::NeutralSummaryCallable).hasManualModel()
}
/** Holds if this API has a manual MaD model. */
predicate hasManualMadModel() { this.hasManualSummary() or this.hasManualNeutral() }
predicate hasManualMadModel() { this.hasManualSummary() or this.hasManualNeutralSummary() }
/*
* Note: the following top JDK APIs are not modeled with MaD:
* `java.lang.Runnable#run()`: specialised lambda flow

View File

@@ -79,7 +79,7 @@ class ExternalApi extends Callable {
/** Holds if this API is a known neutral. */
pragma[nomagic]
predicate isNeutral() { this = any(FlowSummaryImpl::Public::NeutralCallable nsc).asCallable() }
predicate isNeutral() { this instanceof FlowSummaryImpl::Public::NeutralCallable }
/**
* Holds if this API is supported by existing CodeQL libraries, that is, it is either a

View File

@@ -11,7 +11,7 @@ where
// top jdk api names for which there isn't a manual model
exists(TopJdkApi topApi |
not topApi.hasManualMadModel() and
hasApiName(topApi.asCallable(), apiName) and
hasApiName(topApi, apiName) and
message = "no manual model"
)
select apiName, message order by apiName

View File

@@ -1,5 +1,6 @@
| java.io.File#File(String) | 2 |
| java.net.URL#URL(String) | 2 |
| java.io.File#compareTo(File) | 1 |
| java.io.FileWriter#FileWriter(File) | 1 |
| java.lang.StringBuilder#append(String) | 1 |
| java.lang.StringBuilder#toString() | 1 |

View File

@@ -17,7 +17,7 @@ class SupportedExternalApis {
map.put("foo", new Object()); // supported summary
map.entrySet().iterator().next().getKey(); // nested class (Map.Entry), supported summaries (entrySet, iterator, next, getKey)
Duration d = java.time.Duration.ofMillis(1000); // supported neutral
Duration d = java.time.Duration.ofMillis(1000); // supported neutral summary
URL github = new URL("https://www.github.com/"); // supported summary
InputStream stream = github.openConnection().getInputStream(); // supported source (getInputStream), supported sink (openConnection)
@@ -25,6 +25,9 @@ class SupportedExternalApis {
new FileWriter(new File("foo")); // supported sink (FileWriter), supported summary (File)
new URL("http://foo").openStream(); // supported sink (openStream), supported summary (URL)
FileUtils.deleteDirectory(new File("foo")); // supported neutral (deleteDirectory), supported summary (File)
File file = new File("foo"); // supported summary (File)
FileUtils.deleteDirectory(file); // supported neutral summary (deleteDirectory)
file.compareTo(file); // supported neutral sink (compareTo)
}
}

View File

@@ -11,15 +11,15 @@ class ExternalApiUsage {
Map<String, Object> map = new HashMap<>();
map.put("foo", new Object());
Duration d = java.time.Duration.ofMillis(1000); // supported as a neutral model
Duration d = java.time.Duration.ofMillis(1000); // supported as a neutral summary model
long l = "foo".length(); // supported as a neutral model
long l = "foo".length(); // supported as a neutral summary model
AtomicReference<String> ref = new AtomicReference<>(); // uninteresting (parameterless constructor)
ref.set("foo"); // supported as a summary model
ref.toString(); // not supported
String.class.isAssignableFrom(Object.class); // parameter with generic type, supported as a neutral model
String.class.isAssignableFrom(Object.class); // parameter with generic type, supported as a neutral summary model
System.out.println(d);
System.out.println(map);

View File

@@ -296,11 +296,21 @@ module Public {
predicate hasProvenance(Provenance provenance) { provenance = "manual" }
}
/** A callable where there is no flow via the callable. */
class NeutralCallable extends SummarizedCallableBase {
/**
* A callable where there is no flow via the callable.
*/
class NeutralSummaryCallable extends NeutralCallable {
NeutralSummaryCallable() { this.getKind() = "summary" }
}
/**
* A callable that has a neutral model.
*/
class NeutralCallable extends NeutralCallableBase {
private string kind;
private Provenance provenance;
NeutralCallable() { neutralSummaryElement(this, provenance) }
NeutralCallable() { neutralElement(this, kind, provenance) }
/**
* Holds if the neutral is auto generated.
@@ -316,6 +326,11 @@ module Public {
* Holds if the neutral has provenance `p`.
*/
predicate hasProvenance(Provenance p) { p = provenance }
/**
* Gets the kind of the neutral.
*/
string getKind() { result = kind }
}
}
@@ -1318,6 +1333,11 @@ module Private {
/** Gets the string representation of this callable used by `neutral/1`. */
abstract string getCallableCsv();
/**
* Gets the kind of the neutral.
*/
string getKind() { result = super.getKind() }
string toString() { result = super.toString() }
}
@@ -1358,12 +1378,13 @@ module Private {
/**
* Holds if a neutral model `csv` exists (semi-colon separated format). Used for testing purposes.
* The syntax is: "namespace;type;name;signature;provenance"",
* The syntax is: "namespace;type;name;signature;kind;provenance"",
*/
query predicate neutral(string csv) {
exists(RelevantNeutralCallable c |
csv =
c.getCallableCsv() // Callable information
+ c.getKind() + ";" // kind
+ renderProvenanceNeutral(c) // provenance
)
}

View File

@@ -39,8 +39,16 @@ private import FlowSummaryImpl::Private
private import FlowSummaryImpl::Public
private import semmle.python.dataflow.new.FlowSummary as FlowSummary
/**
* A class of callables that are candidates for flow summary modeling.
*/
class SummarizedCallableBase = string;
/**
* A class of callables that are candidates for neutral modeling.
*/
class NeutralCallableBase = string;
/** View a `SummarizedCallable` as a `DataFlowCallable`. */
DataFlowCallable inject(SummarizedCallable c) { result.asLibraryCallable() = c }
@@ -91,11 +99,11 @@ predicate summaryElement(
}
/**
* Holds if a neutral summary model exists for `c` with provenance `provenance`,
* which means that there is no flow through `c`.
* Holds if a neutral model exists for `c` of kind `kind`
* and with provenance `provenance`.
* Note. Neutral models have not been implemented for Python.
*/
predicate neutralSummaryElement(FlowSummary::SummarizedCallable c, string provenance) { none() }
predicate neutralElement(NeutralCallableBase c, string kind, string provenance) { none() }
/**
* Gets the summary component for specification component `c`, if any.

View File

@@ -296,11 +296,21 @@ module Public {
predicate hasProvenance(Provenance provenance) { provenance = "manual" }
}
/** A callable where there is no flow via the callable. */
class NeutralCallable extends SummarizedCallableBase {
/**
* A callable where there is no flow via the callable.
*/
class NeutralSummaryCallable extends NeutralCallable {
NeutralSummaryCallable() { this.getKind() = "summary" }
}
/**
* A callable that has a neutral model.
*/
class NeutralCallable extends NeutralCallableBase {
private string kind;
private Provenance provenance;
NeutralCallable() { neutralSummaryElement(this, provenance) }
NeutralCallable() { neutralElement(this, kind, provenance) }
/**
* Holds if the neutral is auto generated.
@@ -316,6 +326,11 @@ module Public {
* Holds if the neutral has provenance `p`.
*/
predicate hasProvenance(Provenance p) { p = provenance }
/**
* Gets the kind of the neutral.
*/
string getKind() { result = kind }
}
}
@@ -1318,6 +1333,11 @@ module Private {
/** Gets the string representation of this callable used by `neutral/1`. */
abstract string getCallableCsv();
/**
* Gets the kind of the neutral.
*/
string getKind() { result = super.getKind() }
string toString() { result = super.toString() }
}
@@ -1358,12 +1378,13 @@ module Private {
/**
* Holds if a neutral model `csv` exists (semi-colon separated format). Used for testing purposes.
* The syntax is: "namespace;type;name;signature;provenance"",
* The syntax is: "namespace;type;name;signature;kind;provenance"",
*/
query predicate neutral(string csv) {
exists(RelevantNeutralCallable c |
csv =
c.getCallableCsv() // Callable information
+ c.getKind() + ";" // kind
+ renderProvenanceNeutral(c) // provenance
)
}

View File

@@ -11,8 +11,16 @@ private import FlowSummaryImpl::Private
private import FlowSummaryImpl::Public
private import codeql.ruby.dataflow.FlowSummary as FlowSummary
/**
* A class of callables that are candidates for flow summary modeling.
*/
class SummarizedCallableBase = string;
/**
* A class of callables that are candidates for neutral modeling.
*/
class NeutralCallableBase = string;
DataFlowCallable inject(SummarizedCallable c) { result.asLibraryCallable() = c }
/** Gets the parameter position representing a callback itself, if any. */
@@ -62,11 +70,11 @@ predicate summaryElement(
}
/**
* Holds if a neutral summary model exists for `c` with provenance `provenance`,
* which means that there is no flow through `c`.
* Holds if a neutral model exists for `c` of kind `kind`
* and with provenance `provenance`.
* Note. Neutral models have not been implemented for Ruby.
*/
predicate neutralSummaryElement(FlowSummary::SummarizedCallable c, string provenance) { none() }
predicate neutralElement(NeutralCallableBase c, string kind, string provenance) { none() }
bindingset[arg]
private SummaryComponent interpretElementArg(string arg) {

View File

@@ -296,11 +296,21 @@ module Public {
predicate hasProvenance(Provenance provenance) { provenance = "manual" }
}
/** A callable where there is no flow via the callable. */
class NeutralCallable extends SummarizedCallableBase {
/**
* A callable where there is no flow via the callable.
*/
class NeutralSummaryCallable extends NeutralCallable {
NeutralSummaryCallable() { this.getKind() = "summary" }
}
/**
* A callable that has a neutral model.
*/
class NeutralCallable extends NeutralCallableBase {
private string kind;
private Provenance provenance;
NeutralCallable() { neutralSummaryElement(this, provenance) }
NeutralCallable() { neutralElement(this, kind, provenance) }
/**
* Holds if the neutral is auto generated.
@@ -316,6 +326,11 @@ module Public {
* Holds if the neutral has provenance `p`.
*/
predicate hasProvenance(Provenance p) { p = provenance }
/**
* Gets the kind of the neutral.
*/
string getKind() { result = kind }
}
}
@@ -1318,6 +1333,11 @@ module Private {
/** Gets the string representation of this callable used by `neutral/1`. */
abstract string getCallableCsv();
/**
* Gets the kind of the neutral.
*/
string getKind() { result = super.getKind() }
string toString() { result = super.toString() }
}
@@ -1358,12 +1378,13 @@ module Private {
/**
* Holds if a neutral model `csv` exists (semi-colon separated format). Used for testing purposes.
* The syntax is: "namespace;type;name;signature;provenance"",
* The syntax is: "namespace;type;name;signature;kind;provenance"",
*/
query predicate neutral(string csv) {
exists(RelevantNeutralCallable c |
csv =
c.getCallableCsv() // Callable information
+ c.getKind() + ";" // kind
+ renderProvenanceNeutral(c) // provenance
)
}

View File

@@ -13,8 +13,16 @@ private import codeql.swift.dataflow.ExternalFlow
private import codeql.swift.dataflow.FlowSummary as FlowSummary
private import codeql.swift.controlflow.CfgNodes
/**
* A class of callables that are candidates for flow summary modeling.
*/
class SummarizedCallableBase = Function;
/**
* A class of callables that are candidates for neutral modeling.
*/
class NeutralCallableBase = Function;
DataFlowCallable inject(SummarizedCallable c) { result.getUnderlyingCallable() = c }
/** Gets the parameter position of the instance parameter. */
@@ -62,10 +70,11 @@ predicate summaryElement(Function c, string input, string output, string kind, s
}
/**
* Holds if a neutral summary model exists for `c` with provenance `provenance`,
* which means that there is no flow through `c`.
* Holds if a neutral model exists for `c` of kind `kind`
* and with provenance `provenance`.
* Note. Neutral models have not been implemented for Swift.
*/
predicate neutralSummaryElement(Function c, string provenance) { none() }
predicate neutralElement(NeutralCallableBase c, string kind, string provenance) { none() }
/**
* Holds if an external source specification exists for `e` with output specification