Skip to content

Commit d957359

Browse files
authored
Merge pull request github#16810 from smowton/smowton/feature/java-low-db-quality-query
Java: add diagnostic query indicating low database quality
2 parents 31a5a7a + c4f32ec commit d957359

File tree

7 files changed

+126
-59
lines changed

7 files changed

+126
-59
lines changed

.github/workflows/compile-queries.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ jobs:
2929
key: all-queries
3030
- name: check formatting
3131
run: find shared */ql -type f \( -name "*.qll" -o -name "*.ql" \) -print0 | xargs -0 -n 3000 -P 10 codeql query format -q --check-only
32+
- name: Omit DatabaseQualityDiagnostics.ql from compile checking # Remove me once CodeQL 2.18.0 is released!
33+
run: mv java/ql/src/Telemetry/DatabaseQualityDiagnostics.ql{,.hidden}
3234
- name: compile queries - check-only
3335
# run with --check-only if running in a PR (github.sha != main)
3436
if : ${{ github.event_name == 'pull_request' }}
@@ -39,3 +41,6 @@ jobs:
3941
if : ${{ github.event_name != 'pull_request' }}
4042
shell: bash
4143
run: codeql query compile -q -j0 */ql/{src,examples} --keep-going --warnings=error --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}" --compilation-cache-size=500
44+
- name: Restore DatabaseQualityDiagnostics.ql after compile checking # Remove me once CodeQL 2.18.0 is released
45+
run: mv java/ql/src/Telemetry/DatabaseQualityDiagnostics.ql{.hidden,}
46+
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
diagnosticAttributes
2+
| Scanning Java code completed successfully, but the scan encountered issues. This may be caused by problems identifying dependencies or use of generated source code, among other reasons -- see other CodeQL diagnostics reported on the CodeQL status page for more details of possible causes. Addressing these warnings is advisable to avoid false-positive or missing results. If they cannot be addressed, consider scanning Java using either the `autobuild` or `manual` [build modes](https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages#comparison-of-the-build-modes). | visibilityCliSummaryTable | true |
3+
| Scanning Java code completed successfully, but the scan encountered issues. This may be caused by problems identifying dependencies or use of generated source code, among other reasons -- see other CodeQL diagnostics reported on the CodeQL status page for more details of possible causes. Addressing these warnings is advisable to avoid false-positive or missing results. If they cannot be addressed, consider scanning Java using either the `autobuild` or `manual` [build modes](https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages#comparison-of-the-build-modes). | visibilityStatusPage | true |
4+
| Scanning Java code completed successfully, but the scan encountered issues. This may be caused by problems identifying dependencies or use of generated source code, among other reasons -- see other CodeQL diagnostics reported on the CodeQL status page for more details of possible causes. Addressing these warnings is advisable to avoid false-positive or missing results. If they cannot be addressed, consider scanning Java using either the `autobuild` or `manual` [build modes](https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages#comparison-of-the-build-modes). | visibilityTelemetry | true |
5+
#select
6+
| Scanning Java code completed successfully, but the scan encountered issues. This may be caused by problems identifying dependencies or use of generated source code, among other reasons -- see other CodeQL diagnostics reported on the CodeQL status page for more details of possible causes. Addressing these warnings is advisable to avoid false-positive or missing results. If they cannot be addressed, consider scanning Java using either the `autobuild` or `manual` [build modes](https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages#comparison-of-the-build-modes). | Scanning Java code completed successfully, but the scan encountered issues. This may be caused by problems identifying dependencies or use of generated source code, among other reasons -- see other CodeQL diagnostics reported on the CodeQL status page for more details of possible causes. Addressing these warnings is advisable to avoid false-positive or missing results. If they cannot be addressed, consider scanning Java using either the `autobuild` or `manual` [build modes](https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages#comparison-of-the-build-modes). | 1 |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Telemetry/DatabaseQualityDiagnostics.ql
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Java build-mode `none` analyses now only report a warning on the CodeQL status page when there are significant analysis problems-- defined as 5% of expressions lacking a type, or 5% of call targets being unknown. Other messages reported on the status page are downgraded from warnings to notes and so are less prominent, but are still available for review.
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/**
2+
* Provides database quality statistics that are reported by java/telemetry/extractor-information
3+
* and perhaps warned about by java/diagnostics/database-quality.
4+
*/
5+
6+
import java
7+
8+
signature module StatsSig {
9+
int getNumberOfOk();
10+
11+
int getNumberOfNotOk();
12+
13+
string getOkText();
14+
15+
string getNotOkText();
16+
}
17+
18+
module ReportStats<StatsSig Stats> {
19+
predicate numberOfOk(string key, int value) {
20+
value = Stats::getNumberOfOk() and
21+
key = "Number of " + Stats::getOkText()
22+
}
23+
24+
predicate numberOfNotOk(string key, int value) {
25+
value = Stats::getNumberOfNotOk() and
26+
key = "Number of " + Stats::getNotOkText()
27+
}
28+
29+
predicate percentageOfOk(string key, float value) {
30+
value = Stats::getNumberOfOk() * 100.0 / (Stats::getNumberOfOk() + Stats::getNumberOfNotOk()) and
31+
key = "Percentage of " + Stats::getOkText()
32+
}
33+
}
34+
35+
module CallTargetStats implements StatsSig {
36+
int getNumberOfOk() { result = count(Call c | exists(c.getCallee())) }
37+
38+
int getNumberOfNotOk() { result = count(Call c | not exists(c.getCallee())) }
39+
40+
string getOkText() { result = "calls with call target" }
41+
42+
string getNotOkText() { result = "calls with missing call target" }
43+
}
44+
45+
private class SourceExpr extends Expr {
46+
SourceExpr() { this.getFile().isSourceFile() }
47+
}
48+
49+
private predicate hasGoodType(Expr e) {
50+
exists(e.getType()) and not e.getType() instanceof ErrorType
51+
}
52+
53+
module ExprTypeStats implements StatsSig {
54+
int getNumberOfOk() { result = count(SourceExpr e | hasGoodType(e)) }
55+
56+
int getNumberOfNotOk() { result = count(SourceExpr e | not hasGoodType(e)) }
57+
58+
string getOkText() { result = "expressions with known type" }
59+
60+
string getNotOkText() { result = "expressions with unknown type" }
61+
}
62+
63+
module CallTargetStatsReport = ReportStats<CallTargetStats>;
64+
65+
module ExprTypeStatsReport = ReportStats<ExprTypeStats>;
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* @name Low Java analysis quality
3+
* @description Low Java analysis quality
4+
* @kind diagnostic
5+
* @id java/diagnostic/database-quality
6+
*/
7+
8+
import java
9+
import DatabaseQuality
10+
11+
private newtype TDbQualityDiagnostic =
12+
TTheDbQualityDiagnostic() {
13+
exists(float percentageGood |
14+
CallTargetStatsReport::percentageOfOk(_, percentageGood)
15+
or
16+
ExprTypeStatsReport::percentageOfOk(_, percentageGood)
17+
|
18+
percentageGood < 95
19+
)
20+
}
21+
22+
class DbQualityDiagnostic extends TDbQualityDiagnostic {
23+
string toString() {
24+
result =
25+
"Scanning Java code completed successfully, but the scan encountered issues. " +
26+
"This may be caused by problems identifying dependencies or use of generated source code, among other reasons -- "
27+
+
28+
"see other CodeQL diagnostics reported on the CodeQL status page for more details of possible causes. "
29+
+
30+
"Addressing these warnings is advisable to avoid false-positive or missing results. If they cannot be addressed, consider scanning Java "
31+
+
32+
"using either the `autobuild` or `manual` [build modes](https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages#comparison-of-the-build-modes)."
33+
}
34+
}
35+
36+
query predicate diagnosticAttributes(DbQualityDiagnostic e, string key, string value) {
37+
e = e and // Quieten warning about unconstrained 'e'
38+
key = ["visibilityCliSummaryTable", "visibilityTelemetry", "visibilityStatusPage"] and
39+
value = "true"
40+
}
41+
42+
from DbQualityDiagnostic d
43+
select d, d.toString(), 1
44+
/* Warning severity */

java/ql/src/Telemetry/ExtractorInformation.ql

Lines changed: 1 addition & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import java
1010
import semmle.code.java.Diagnostics
11+
import DatabaseQuality
1112

1213
extensible predicate extractorInformationSkipKey(string key);
1314

@@ -85,65 +86,6 @@ predicate extractorTotalDiagnostics(string key, int value) {
8586
)
8687
}
8788

88-
signature module StatsSig {
89-
int getNumberOfOk();
90-
91-
int getNumberOfNotOk();
92-
93-
string getOkText();
94-
95-
string getNotOkText();
96-
}
97-
98-
module ReportStats<StatsSig Stats> {
99-
predicate numberOfOk(string key, int value) {
100-
value = Stats::getNumberOfOk() and
101-
key = "Number of " + Stats::getOkText()
102-
}
103-
104-
predicate numberOfNotOk(string key, int value) {
105-
value = Stats::getNumberOfNotOk() and
106-
key = "Number of " + Stats::getNotOkText()
107-
}
108-
109-
predicate percentageOfOk(string key, float value) {
110-
value = Stats::getNumberOfOk() * 100.0 / (Stats::getNumberOfOk() + Stats::getNumberOfNotOk()) and
111-
key = "Percentage of " + Stats::getOkText()
112-
}
113-
}
114-
115-
module CallTargetStats implements StatsSig {
116-
int getNumberOfOk() { result = count(Call c | exists(c.getCallee())) }
117-
118-
int getNumberOfNotOk() { result = count(Call c | not exists(c.getCallee())) }
119-
120-
string getOkText() { result = "calls with call target" }
121-
122-
string getNotOkText() { result = "calls with missing call target" }
123-
}
124-
125-
private class SourceExpr extends Expr {
126-
SourceExpr() { this.getFile().isSourceFile() }
127-
}
128-
129-
private predicate hasGoodType(Expr e) {
130-
exists(e.getType()) and not e.getType() instanceof ErrorType
131-
}
132-
133-
module ExprTypeStats implements StatsSig {
134-
int getNumberOfOk() { result = count(SourceExpr e | hasGoodType(e)) }
135-
136-
int getNumberOfNotOk() { result = count(SourceExpr e | not hasGoodType(e)) }
137-
138-
string getOkText() { result = "expressions with known type" }
139-
140-
string getNotOkText() { result = "expressions with unknown type" }
141-
}
142-
143-
module CallTargetStatsReport = ReportStats<CallTargetStats>;
144-
145-
module ExprTypeStatsReport = ReportStats<ExprTypeStats>;
146-
14789
from string key, int value
14890
where
14991
not exists(string pattern | extractorInformationSkipKey(pattern) and key.matches(pattern)) and

0 commit comments

Comments
 (0)