Skip to content

Commit 19fa29d

Browse files
authored
Merge pull request #20307 from asgerf/js/overlay-extract-and-discard-only
JS: Add overlay support to extractor
2 parents 9bae0bf + 67a1c2f commit 19fa29d

File tree

13 files changed

+4939
-1
lines changed

13 files changed

+4939
-1
lines changed

javascript/downgrades/76a926a00d5f3bc199c203a1437796fd7b2835ba/old.dbscheme

Lines changed: 1204 additions & 0 deletions
Large diffs are not rendered by default.

javascript/downgrades/76a926a00d5f3bc199c203a1437796fd7b2835ba/semmlecode.javascript.dbscheme

Lines changed: 1194 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
description: downgrade overlay relations
2+
compatibility: full
3+
4+
databaseMetadata.rel: delete
5+
overlayChangedFiles.rel: delete

javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,10 +465,11 @@ public int run() throws IOException {
465465
try {
466466
CompletableFuture<?> sourceFuture = extractSource();
467467
sourceFuture.join(); // wait for source extraction to complete
468-
if (hasSeenCode()) { // don't bother with the externs if no code was seen
468+
if (hasSeenCode() && !isOverlayChangeMode()) { // don't bother with the externs if no code was seen or in overlay change mode
469469
extractExterns();
470470
}
471471
extractXml();
472+
writeOverlayMetadata();
472473
} catch (OutOfMemoryError oom) {
473474
System.err.println("Out of memory while extracting the project.");
474475
return 137; // the CodeQL CLI will interpret this as an out-of-memory error
@@ -509,6 +510,21 @@ public int run() throws IOException {
509510
return 0;
510511
}
511512

513+
private void writeOverlayMetadata() {
514+
String file = getEnvVar("CODEQL_EXTRACTOR_JAVASCRIPT_OVERLAY_BASE_METADATA_OUT");
515+
if (file == null) {
516+
// no overlay metadata file specified, so nothing to do
517+
return;
518+
}
519+
// Write an empty string to the file as we currently have no metadata to emit.
520+
// The file must be created for the database to recognized as an overlay base.
521+
try {
522+
Files.writeString(Paths.get(file), "", StandardCharsets.UTF_8);
523+
} catch (IOException e) {
524+
throw new ResourceError("Could not write overlay metadata to " + file, e);
525+
}
526+
}
527+
512528
/**
513529
* A kind of error that can happen during extraction of JavaScript or TypeScript
514530
* code.
@@ -734,6 +750,17 @@ private CompletableFuture<?> extractSource() throws IOException {
734750
List<Path> tsconfigFiles = new ArrayList<>();
735751
findFilesToExtract(defaultExtractor, filesToExtract, tsconfigFiles);
736752

753+
OverlayChanges overlay = getOverlayChanges();
754+
if (overlay != null) {
755+
Set<Path> changedFiles = overlay.changes.stream()
756+
.map(file -> Paths.get(file).toAbsolutePath())
757+
.collect(Collectors.toSet());
758+
int before = filesToExtract.size();
759+
filesToExtract.retainAll(changedFiles);
760+
int after = filesToExtract.size();
761+
System.out.println("Overlay filter removed " + (before - after) + " out of " + before + " files from extraction.");
762+
}
763+
737764
tsconfigFiles = tsconfigFiles.stream()
738765
.sorted(PATH_ORDERING)
739766
.collect(Collectors.toList());
@@ -1338,6 +1365,18 @@ protected void extractXml() throws IOException {
13381365
}
13391366
}
13401367

1368+
private boolean isOverlayChangeMode() {
1369+
return getEnvVar("CODEQL_EXTRACTOR_JAVASCRIPT_OVERLAY_CHANGES") != null;
1370+
}
1371+
1372+
private OverlayChanges getOverlayChanges() throws IOException {
1373+
String jsonFile = getEnvVar("CODEQL_EXTRACTOR_JAVASCRIPT_OVERLAY_CHANGES");
1374+
if (jsonFile == null) {
1375+
return null;
1376+
}
1377+
return new Gson().fromJson(Files.newBufferedReader(Paths.get(jsonFile)), OverlayChanges.class);
1378+
}
1379+
13411380
public static void main(String[] args) {
13421381
try {
13431382
System.exit(new AutoBuild().run());
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.semmle.js.extractor;
2+
3+
import java.util.List;
4+
5+
public class OverlayChanges {
6+
public List<String> changes;
7+
}

javascript/ql/lib/javascript.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,3 +146,4 @@ import semmle.javascript.linters.JSLint
146146
import semmle.javascript.linters.Linting
147147
import semmle.javascript.security.dataflow.RemoteFlowSources
148148
import semmle.javascript.frameworks.UnderscoreDotString
149+
private import semmle.javascript.internal.Overlay
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
private import javascript
2+
3+
/** Holds if the database is an overlay. */
4+
overlay[local]
5+
private predicate isOverlay() { databaseMetadata("isOverlay", "true") }
6+
7+
overlay[local]
8+
private string getFileFromEntity(@locatable node) {
9+
exists(@location loc, @file file |
10+
hasLocation(node, loc) and
11+
locations_default(loc, file, _, _, _, _) and
12+
files(file, result)
13+
)
14+
}
15+
16+
/** Holds if `file` was changed or deleted in the overlay. */
17+
overlay[local]
18+
private predicate discardFile(string file) { isOverlay() and overlayChangedFiles(file) }
19+
20+
/** Holds if `node` is in the `file` and is part of the overlay base database. */
21+
overlay[local]
22+
private predicate discardableEntity(string file, @locatable node) {
23+
not isOverlay() and file = getFileFromEntity(node)
24+
}
25+
26+
/** Holds if `node` should be discarded, because it is part of the overlay base and is in a file that was also extracted as part of the overlay database. */
27+
overlay[discard_entity]
28+
private predicate discardEntity(@locatable node) {
29+
exists(string file | discardableEntity(file, node) and discardFile(file))
30+
}

javascript/ql/lib/semmlecode.javascript.dbscheme

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,3 +1192,13 @@ configLocations(
11921192
);
11931193

11941194
@configLocatable = @config | @configName | @configValue;
1195+
1196+
/*- Database metadata -*/
1197+
databaseMetadata(
1198+
string metadataKey: string ref,
1199+
string value: string ref
1200+
);
1201+
1202+
overlayChangedFiles(
1203+
string path: string ref
1204+
);

javascript/ql/lib/semmlecode.javascript.dbscheme.stats

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28260,5 +28260,52 @@
2826028260
</dep>
2826128261
</dependencies>
2826228262
</relation>
28263+
<relation>
28264+
<name>databaseMetadata</name>
28265+
<cardinality>1</cardinality>
28266+
<columnsizes>
28267+
<e>
28268+
<k>metadataKey</k>
28269+
<v>1</v>
28270+
</e>
28271+
<e>
28272+
<k>value</k>
28273+
<v>1</v>
28274+
</e>
28275+
</columnsizes>
28276+
<dependencies>
28277+
<dep>
28278+
<src>metadataKey</src>
28279+
<trg>value</trg>
28280+
<val>
28281+
<hist>
28282+
<budget>12</budget>
28283+
<bs/>
28284+
</hist>
28285+
</val>
28286+
</dep>
28287+
<dep>
28288+
<src>value</src>
28289+
<trg>metadataKey</trg>
28290+
<val>
28291+
<hist>
28292+
<budget>12</budget>
28293+
<bs/>
28294+
</hist>
28295+
</val>
28296+
</dep>
28297+
</dependencies>
28298+
</relation>
28299+
<relation>
28300+
<name>overlayChangedFiles</name>
28301+
<cardinality>50</cardinality>
28302+
<columnsizes>
28303+
<e>
28304+
<k>path</k>
28305+
<v>50</v>
28306+
</e>
28307+
</columnsizes>
28308+
<dependencies/>
28309+
</relation>
2826328310
</stats>
2826428311
</dbstats>

0 commit comments

Comments
 (0)