From 965cc60752c8e8625dd0711af6f5c56756b1f68d Mon Sep 17 00:00:00 2001 From: Dar Malovani Date: Tue, 25 May 2021 17:23:31 +0300 Subject: [PATCH 1/3] feat: continue scan if reachability fails On the reachability maven flow, if there's a call graph error we continue the scan without exploding. This employ the same logic. --- lib/index.ts | 34 +++++++++++++++++++++++++++----- test/system/reachability.test.ts | 27 ++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 6 deletions(-) diff --git a/lib/index.ts b/lib/index.ts index 2ec2971..0dfac90 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -13,6 +13,7 @@ import debugModule = require('debug'); type ScannedProject = legacyCommon.ScannedProject; type CallGraph = legacyCommon.CallGraph; +type CallGraphResult = legacyCommon.CallGraphResult; // To enable debugging output, use `snyk -d` let logger: debugModule.Debugger | null = null; @@ -111,7 +112,7 @@ export async function inspect( meta: {}, }; - let callGraph: CallGraph | undefined; + let callGraph: CallGraphResult | undefined; const targetPath = path.join(root, targetFile); if (options.reachableVulns) { @@ -131,14 +132,12 @@ export async function inspect( confAttrs = options['configuration-attributes']; } - debugLog(`getting call graph from path ${targetPath}`); - callGraph = await javaCallGraphBuilder.getCallGraphGradle( - path.dirname(targetPath), + callGraph = await getCallGraph( + targetPath, command, initScriptPath, confAttrs, ); - debugLog('got call graph successfully'); } if (api.isMultiSubProject(options)) { @@ -765,6 +764,31 @@ function buildArgs( return args; } +async function getCallGraph( + targetPath: string, + command: string, + initScriptPath?: string, + confAttrs?: string, +): Promise { + try { + debugLog(`getting call graph from path ${targetPath}`); + const callGraph: CallGraph = await javaCallGraphBuilder.getCallGraphGradle( + path.dirname(targetPath), + command, + initScriptPath, + confAttrs, + ); + debugLog('got call graph successfully'); + return callGraph; + } catch (e) { + debugLog('call graph error: ' + e); + return { + message: e.message, + innerError: e.innerError || e, + }; + } +} + export const exportsForTests = { buildArgs, extractJsonFromScriptOutput, diff --git a/test/system/reachability.test.ts b/test/system/reachability.test.ts index b02aae1..ea4bae4 100644 --- a/test/system/reachability.test.ts +++ b/test/system/reachability.test.ts @@ -5,7 +5,7 @@ import { inspect, formatArgWithWhiteSpace } from '../../lib'; import * as fs from 'fs'; import * as sinon from 'sinon'; import * as javaCallGraphBuilder from '@snyk/java-call-graph-builder'; -import { CallGraph } from '@snyk/cli-interface/legacy/common'; +import { CallGraph, CallGraphError } from '@snyk/cli-interface/legacy/common'; const rootNoWrapper = fixtureDir('no wrapper'); @@ -117,3 +117,28 @@ test('reachableVulns', async (t) => { javaCallGraphBuilderStub.restore(); }); }); + +test('failure modes', async (t) => { + t.test('gracefully fails', async (t) => { + const errorMessage = 'Call graph error'; + const javaCallGraphBuilderFailedStub = sinon + .stub(javaCallGraphBuilder, 'getCallGraphGradle') + .rejects(new Error(errorMessage)); + + const result = await inspect( + '.', + path.join(rootNoWrapper, 'build.gradle'), + { + reachableVulns: true, + }, + ); + + t.same( + errorMessage, + (result.callGraph as CallGraphError).message, + 'get correct error message', + ); + + javaCallGraphBuilderFailedStub.restore(); + }); +}); From c26396fdd80beec8457c3181cadc582cd2b1d53a Mon Sep 17 00:00:00 2001 From: Dar Malovani Date: Tue, 25 May 2021 17:26:26 +0300 Subject: [PATCH 2/3] feat: support timeout for gradle call graph creation --- lib/index.ts | 8 ++++++++ test/system/reachability.test.ts | 23 +++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/lib/index.ts b/lib/index.ts index 0dfac90..5ca3f6c 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -64,6 +64,7 @@ export interface GradleInspectOptions { // Leaving default usage `--no-daemon`, because of backwards compatibility daemon?: boolean; reachableVulns?: boolean; + callGraphBuilderTimeout?: number; initScript?: string; } @@ -132,11 +133,16 @@ export async function inspect( confAttrs = options['configuration-attributes']; } + const timeout = options?.callGraphBuilderTimeout + ? options?.callGraphBuilderTimeout * 1000 + : undefined; + callGraph = await getCallGraph( targetPath, command, initScriptPath, confAttrs, + timeout, ); } @@ -769,6 +775,7 @@ async function getCallGraph( command: string, initScriptPath?: string, confAttrs?: string, + timeout?: number, ): Promise { try { debugLog(`getting call graph from path ${targetPath}`); @@ -777,6 +784,7 @@ async function getCallGraph( command, initScriptPath, confAttrs, + timeout, ); debugLog('got call graph successfully'); return callGraph; diff --git a/test/system/reachability.test.ts b/test/system/reachability.test.ts index ea4bae4..548db8c 100644 --- a/test/system/reachability.test.ts +++ b/test/system/reachability.test.ts @@ -113,6 +113,29 @@ test('reachableVulns', async (t) => { ); }); + t.test('with timeout', async (t) => { + const result = await inspect( + '.', + path.join(rootNoWrapper, 'build.gradle'), + { + reachableVulns: true, + callGraphBuilderTimeout: 20, + }, + ); + + t.ok( + javaCallGraphBuilderStub.calledWith( + path.join('.', rootNoWrapper), + 'gradle', + undefined, + undefined, + 20000, + ), + 'call graph builder was called with timeout', + ); + t.same(gradleCallGraph, result.callGraph, 'returns expected callgraph'); + }); + t.teardown(() => { javaCallGraphBuilderStub.restore(); }); From 6dd319248f5abacd916342bfa8d8aa336c30cd10 Mon Sep 17 00:00:00 2001 From: Dar Malovani Date: Tue, 25 May 2021 17:28:02 +0300 Subject: [PATCH 3/3] chore: bump call graph builder to include more debugging context --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index dba8003..0f541fa 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "dependencies": { "@snyk/cli-interface": "2.11.0", "@snyk/dep-graph": "^1.28.0", - "@snyk/java-call-graph-builder": "1.22.0", + "@snyk/java-call-graph-builder": "1.23.0", "@types/debug": "^4.1.4", "chalk": "^3.0.0", "debug": "^4.1.1",