Skip to content

Commit

Permalink
Merge pull request #637 from snyk/fix_common_dir_bug
Browse files Browse the repository at this point in the history
fix: common extracted dir bug
  • Loading branch information
nozik authored Jan 2, 2025
2 parents aa046a2 + 125adfc commit c26df62
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 16 deletions.
37 changes: 23 additions & 14 deletions lib/analyzer/applications/runtime-common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,34 +10,43 @@ export function getAppFilesRootDir(
filePaths: string[],
): [string, ApplicationFileInfo[]] {
const appFiles: ApplicationFileInfo[] = [];
let rootDir: string = "";
const directories: Set<string> = new Set();
const splitPaths: string[][] = [];

if (!filePaths.length) {
return [path.sep, appFiles];
}

for (const filePath of filePaths) {
appFiles.push({ path: filePath });
directories.add(path.dirname(filePath)); // Collect directories of app files
splitPaths.push(filePath.split("/").filter(Boolean));
}

// Determine the common directory
if (appFiles.length > 0) {
rootDir = Array.from(directories).reduce((commonDir, dir) => {
// Find the common path
while (commonDir && commonDir !== "" && !dir.startsWith(commonDir)) {
commonDir = commonDir.substring(0, commonDir.lastIndexOf(path.sep));
}
return commonDir;
}, directories.values().next().value);
// Find the shortest path length to prevent out-of-bounds access
const minLength = Math.min(...splitPaths.map((path) => path.length));

// Find the common parts of the paths
const commonParts: string[] = [];
for (let i = 0; i < minLength - 1; i++) {
const currentPart = splitPaths[0][i];
if (splitPaths.every((path) => path[i] === currentPart)) {
commonParts.push(currentPart);
} else {
break;
}
}

// Join the common parts to form the common directory
const rootDir = "/" + commonParts.join("/");

// Remove the common path prefix from each appFile
appFiles.forEach((file) => {
const prefix = `${rootDir}${path.sep}`;
const prefix = rootDir === path.sep ? rootDir : `${rootDir}${path.sep}`;
if (file.path.startsWith(prefix)) {
file.path = file.path.substring(prefix.length); // Remove rootDir from path
}
});

return [rootDir, appFiles];
return [rootDir || path.sep, appFiles];
}

export function getApplicationFiles(
Expand Down
39 changes: 37 additions & 2 deletions test/system/application-scans/node.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -663,7 +663,18 @@ describe("node application files grouping", () => {
});

it("should correctly group js ts files with root dir", async () => {
const nodeProjectFiles = [
let nodeProjectFiles = [
"/aaa/bbb/ccc/y.js",
"/aaa/bbb/ccc/z.js",
"/aaa/x.js",
];

let [appFilesRootDir, appFiles] = getAppFilesRootDir(nodeProjectFiles);

expect(appFilesRootDir).toBe("/aaa");
expect(appFiles.length).toBe(3);

nodeProjectFiles = [
"/srv/dist/index.js",
"/srv/dist/src/app.js",
"/srv/dist/src/utils/helpers.js",
Expand All @@ -676,7 +687,7 @@ describe("node application files grouping", () => {
"/srv/dist/package-lock.json",
];

const [appFilesRootDir, appFiles] = getAppFilesRootDir(nodeProjectFiles);
[appFilesRootDir, appFiles] = getAppFilesRootDir(nodeProjectFiles);

expect(appFilesRootDir).toBe("/srv/dist");
expect(appFiles.length).toBe(10);
Expand All @@ -693,6 +704,30 @@ describe("node application files grouping", () => {
{ path: "package-lock.json" },
]);
});

it("should return / as the root dir in case nothing's found", async () => {
const nodeProjectFiles = ["/srv/dist/index.js", "/opt/app.js"];

const [appFilesRootDir, appFiles] = getAppFilesRootDir(nodeProjectFiles);
expect(appFilesRootDir).toBe("/");
expect(appFiles.length).toBe(2);
expect(appFiles).toEqual([
{ path: "srv/dist/index.js" },
{ path: "opt/app.js" },
]);
});

it("should only consider full path segments for common prefix", async () => {
const nodeProjectFiles = ["/srv/dist/index.js", "/srv2/app.js"];

const [appFilesRootDir, appFiles] = getAppFilesRootDir(nodeProjectFiles);
expect(appFilesRootDir).toBe("/");
expect(appFiles.length).toBe(2);
expect(appFiles).toEqual([
{ path: "srv/dist/index.js" },
{ path: "srv2/app.js" },
]);
});
});

describe("Edge testing of node modules scan utils functions", () => {
Expand Down

0 comments on commit c26df62

Please sign in to comment.