Skip to content

Commit 59682d4

Browse files
Fix issue with large SARIF files crashing view
Authored by: Marc Jaramillo marcnjaramillo@github.com Authored by: Musab Guma'a mgsium@github.com
1 parent 20cdca7 commit 59682d4

File tree

1 file changed

+54
-12
lines changed
  • extensions/ql-vscode/src

1 file changed

+54
-12
lines changed

extensions/ql-vscode/src/cli.ts

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@ import * as cpp from 'child-process-promise';
22
import * as child_process from 'child_process';
33
import * as fs from 'fs-extra';
44
import * as path from 'path';
5+
import { parser } from 'stream-json';
6+
import { pick } from 'stream-json/filters/Pick';
7+
import { verifier } from 'stream-json/utils/Verifier';
8+
import Assembler = require('stream-json/Assembler');
9+
import { chain } from 'stream-chain';
510
import * as sarif from 'sarif';
611
import { SemVer } from 'semver';
712
import { Readable } from 'stream';
@@ -669,19 +674,56 @@ export class CodeQLCliServer implements Disposable {
669674

670675
async interpretBqrs(metadata: QueryMetadata, resultsPath: string, interpretedResultsPath: string, sourceInfo?: SourceInfo): Promise<sarif.Log> {
671676
await this.runInterpretCommand(SARIF_FORMAT, metadata, resultsPath, interpretedResultsPath, sourceInfo);
672-
673-
let output: string;
674-
try {
675-
output = await fs.readFile(interpretedResultsPath, 'utf8');
676-
} catch (e) {
677-
const rawMessage = e.stderr || e.message;
678-
const errorMessage = rawMessage.startsWith('Cannot create a string')
679-
? `SARIF too large. ${rawMessage}`
680-
: rawMessage;
681-
throw new Error(`Reading output of interpretation failed: ${errorMessage}`);
682-
}
683677
try {
684-
return JSON.parse(output) as sarif.Log;
678+
// Parse the SARIF file into token streams, filtering out only the results array.
679+
const p = parser();
680+
const pipeline = chain([
681+
fs.createReadStream(interpretedResultsPath),
682+
p,
683+
pick({filter: 'runs.0.results'}),
684+
verifier()
685+
]);
686+
687+
// Creates JavaScript objects from the token stream
688+
const asm = Assembler.connectTo(pipeline);
689+
690+
// Returns a constructed Log object with the results or an empty array if no results were found.
691+
// If the parser fails for any reason, it will reject the promise.
692+
return await new Promise((resolve, reject) => {
693+
pipeline.on('error', (error) => {
694+
reject(error);
695+
});
696+
697+
asm.on('done', (asm) => {
698+
const dummyTool : sarif.Tool = {driver: {name: ''}};
699+
if (asm.current) {
700+
const log : sarif.Log = {
701+
version: '2.1.0',
702+
runs: [
703+
{
704+
tool: dummyTool,
705+
results: asm.current
706+
}
707+
]
708+
};
709+
710+
resolve(log);
711+
} else {
712+
const log : sarif.Log = {
713+
version: '2.1.0',
714+
runs: [
715+
{
716+
tool: dummyTool,
717+
results: []
718+
}
719+
]
720+
};
721+
722+
resolve(log);
723+
}
724+
725+
});
726+
});
685727
} catch (err) {
686728
throw new Error(`Parsing output of interpretation failed: ${err.stderr || err}`);
687729
}

0 commit comments

Comments
 (0)