Skip to content

Commit 5623ccf

Browse files
committed
Java: Re-factor NeutralCallable to include all neutrals and introduce NeutralSummaryCallable.
1 parent 6deeb36 commit 5623ccf

File tree

8 files changed

+51
-24
lines changed

8 files changed

+51
-24
lines changed

java/ql/lib/semmle/code/java/dataflow/FlowSummary.qll

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,6 @@ class Provenance = Impl::Public::Provenance;
175175

176176
class SummarizedCallable = Impl::Public::SummarizedCallable;
177177

178-
class NeutralCallable = Impl::Public::NeutralCallable;
179-
180178
/**
181179
* An adapter class to add the flow summaries specified on `SyntheticCallable`
182180
* to `SummarizedCallable`.

java/ql/lib/semmle/code/java/dataflow/internal/DataFlowDispatch.qll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@ private import java
22
private import DataFlowPrivate
33
private import DataFlowUtil
44
private import semmle.code.java.dataflow.InstanceAccess
5-
private import semmle.code.java.dataflow.FlowSummary
5+
private import semmle.code.java.dataflow.internal.FlowSummaryImpl as Impl
66
private import semmle.code.java.dispatch.VirtualDispatch as VirtualDispatch
77
private import semmle.code.java.dataflow.TypeFlow
88
private import semmle.code.java.dispatch.internal.Unification
99

1010
private module DispatchImpl {
1111
private predicate hasHighConfidenceTarget(Call c) {
12-
exists(SummarizedCallable sc | sc.getACall() = c and not sc.applyGeneratedModel())
12+
exists(Impl::Public::SummarizedCallable sc | sc.getACall() = c and not sc.applyGeneratedModel())
1313
or
14-
exists(NeutralCallable nc | nc.getACall() = c and nc.hasManualModel())
14+
exists(Impl::Public::NeutralSummaryCallable nc | nc.getACall() = c and nc.hasManualModel())
1515
or
1616
exists(Callable srcTgt |
1717
srcTgt = VirtualDispatch::viableCallable(c) and

java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -296,11 +296,21 @@ module Public {
296296
predicate hasProvenance(Provenance provenance) { provenance = "manual" }
297297
}
298298

299-
/** A callable where there is no flow via the callable. */
300-
class NeutralCallable extends SummarizedCallableBase {
299+
/**
300+
* A callable where there is no flow via the callable.
301+
*/
302+
class NeutralSummaryCallable extends NeutralCallable {
303+
NeutralSummaryCallable() { this.getKind() = "summary" }
304+
}
305+
306+
/**
307+
* A callable that has a neutral model.
308+
*/
309+
class NeutralCallable extends NeutralCallableBase {
310+
private string kind;
301311
private Provenance provenance;
302312

303-
NeutralCallable() { neutralSummaryElement(this, provenance) }
313+
NeutralCallable() { neutralElement(this, kind, provenance) }
304314

305315
/**
306316
* Holds if the neutral is auto generated.
@@ -316,6 +326,11 @@ module Public {
316326
* Holds if the neutral has provenance `p`.
317327
*/
318328
predicate hasProvenance(Provenance p) { p = provenance }
329+
330+
/**
331+
* Gets the kind of the neutral.
332+
*/
333+
string getKind() { result = kind }
319334
}
320335
}
321336

@@ -1318,6 +1333,8 @@ module Private {
13181333
/** Gets the string representation of this callable used by `neutral/1`. */
13191334
abstract string getCallableCsv();
13201335

1336+
string getKind() { result = super.getKind() }
1337+
13211338
string toString() { result = super.toString() }
13221339
}
13231340

@@ -1364,6 +1381,7 @@ module Private {
13641381
exists(RelevantNeutralCallable c |
13651382
csv =
13661383
c.getCallableCsv() // Callable information
1384+
+ c.getKind() + ";" // kind
13671385
+ renderProvenanceNeutral(c) // provenance
13681386
)
13691387
}

java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImplSpecific.qll

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,16 @@ private import semmle.code.java.dataflow.internal.AccessPathSyntax as AccessPath
1414

1515
class SummarizedCallableBase = FlowSummary::SummarizedCallableBase;
1616

17+
/**
18+
* A class of callables that are candidates for neutral modeling.
19+
*/
20+
class NeutralCallableBase extends Callable {
21+
NeutralCallableBase() { this.isSourceDeclaration() }
22+
23+
/** Gets a call that targets this neutral. */
24+
Call getACall() { result.getCallee().getSourceDeclaration() = this }
25+
}
26+
1727
/**
1828
* A module for importing frameworks that define synthetic globals.
1929
*/
@@ -156,13 +166,13 @@ predicate summaryElement(
156166
}
157167

158168
/**
159-
* Holds if a neutral summary model exists for `c` with provenance `provenance`,
160-
* which means that there is no flow through `c`.
169+
* Holds if a neutral model exists for `c` of kind `kind`
170+
* and with provenance `provenance`.
161171
*/
162-
predicate neutralSummaryElement(SummarizedCallableBase c, string provenance) {
172+
predicate neutralElement(NeutralCallableBase c, string kind, string provenance) {
163173
exists(string namespace, string type, string name, string signature |
164-
neutralModel(namespace, type, name, signature, "summary", provenance) and
165-
c.asCallable() = interpretElement(namespace, type, false, name, signature, "")
174+
neutralModel(namespace, type, name, signature, kind, provenance) and
175+
c = interpretElement(namespace, type, false, name, signature, "")
166176
)
167177
}
168178

java/ql/src/Metrics/Summaries/GeneratedVsManualCoverageQuery.qll

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,10 @@ private int getNumApis(string package, string apiSubset) {
4545

4646
/** Holds if the given `callable` belongs to the specified `apiSubset`. */
4747
private predicate callableSubset(Callable callable, string apiSubset) {
48-
apiSubset in ["topJdkApis", "allApis"] and
49-
(
50-
if apiSubset = "topJdkApis"
51-
then exists(TopJdkApi topJdkApi | callable = topJdkApi.asCallable())
52-
else apiSubset = "allApis"
53-
)
48+
apiSubset = "topJdkApis" and
49+
callable instanceof TopJdkApi
50+
or
51+
apiSubset = "allApis"
5452
}
5553

5654
/**

java/ql/src/Metrics/Summaries/TopJdkApis.qll

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -287,16 +287,19 @@ predicate hasApiName(Callable c, string apiName) {
287287
}
288288

289289
/** A top JDK API. */
290-
class TopJdkApi extends SummarizedCallableBase {
290+
class TopJdkApi extends Callable {
291291
TopJdkApi() {
292+
this.isSourceDeclaration() and
292293
exists(string apiName |
293-
hasApiName(this.asCallable(), apiName) and
294+
hasApiName(this, apiName) and
294295
topJdkApiName(apiName)
295296
)
296297
}
297298

298299
/** Holds if this API has a manual summary model. */
299-
private predicate hasManualSummary() { this.(SummarizedCallable).hasManualModel() }
300+
private predicate hasManualSummary() {
301+
exists(SummarizedCallable sc | sc.asCallable() = this and sc.hasManualModel())
302+
}
300303

301304
/** Holds if this API has a manual neutral model. */
302305
private predicate hasManualNeutral() {

java/ql/src/Telemetry/ExternalApi.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ class ExternalApi extends Callable {
7979

8080
/** Holds if this API is a known neutral. */
8181
pragma[nomagic]
82-
predicate isNeutral() { this = any(FlowSummaryImpl::Public::NeutralCallable nsc).asCallable() }
82+
predicate isNeutral() { this instanceof FlowSummaryImpl::Public::NeutralCallable }
8383

8484
/**
8585
* Holds if this API is supported by existing CodeQL libraries, that is, it is either a

java/ql/test/ext/TopJdkApis/TopJdkApisTest.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ where
1111
// top jdk api names for which there isn't a manual model
1212
exists(TopJdkApi topApi |
1313
not topApi.hasManualMadModel() and
14-
hasApiName(topApi.asCallable(), apiName) and
14+
hasApiName(topApi, apiName) and
1515
message = "no manual model"
1616
)
1717
select apiName, message order by apiName

0 commit comments

Comments
 (0)