From 2f7ffaab6cf90b6db9a1dc07ca9f9e21306698ff Mon Sep 17 00:00:00 2001 From: mkarkkainen <65869801+mkarkkainen@users.noreply.github.com> Date: Wed, 17 Jan 2024 13:51:16 -0600 Subject: [PATCH] refactor: split utils (#209) * refactor: split utils to multiple files #208 * Resolve test errors --- index.js | 2 +- src/SourceFile.js | 2 +- src/obfuscators/jjencode.js | 2 +- src/probes/isArrayExpression.js | 2 +- src/probes/isClassDeclaration.js | 2 +- src/probes/isFunction.js | 2 +- src/probes/isMethodDefinition.js | 2 +- src/probes/isUnsafeCallee.js | 2 +- src/utils.js | 111 ------------------- src/utils/exportAssignmentHasRequireLeave.js | 40 +++++++ src/utils/extractNode.js | 14 +++ src/utils/index.js | 7 ++ src/utils/isOneLineExpressionExport.js | 18 +++ src/utils/isUnsafeCallee.js | 28 +++++ src/utils/notNullOrUndefined.js | 3 + src/utils/rootLocation.js | 3 + src/utils/toArrayLocation.js | 11 ++ src/warnings.js | 2 +- test/warnings.spec.js | 2 +- 19 files changed, 134 insertions(+), 121 deletions(-) delete mode 100644 src/utils.js create mode 100644 src/utils/exportAssignmentHasRequireLeave.js create mode 100644 src/utils/extractNode.js create mode 100644 src/utils/index.js create mode 100644 src/utils/isOneLineExpressionExport.js create mode 100644 src/utils/isUnsafeCallee.js create mode 100644 src/utils/notNullOrUndefined.js create mode 100644 src/utils/rootLocation.js create mode 100644 src/utils/toArrayLocation.js diff --git a/index.js b/index.js index a799e49..162c70e 100644 --- a/index.js +++ b/index.js @@ -10,7 +10,7 @@ import isMinified from "is-minified-code"; import { SourceFile } from "./src/SourceFile.js"; import { SourceParser } from "./src/SourceParser.js"; import { warnings } from "./src/warnings.js"; -import { isOneLineExpressionExport } from "./src/utils.js"; +import { isOneLineExpressionExport } from "./src/utils/index.js"; export function runASTAnalysis( str, diff --git a/src/SourceFile.js b/src/SourceFile.js index 3b6eea2..f90d10b 100644 --- a/src/SourceFile.js +++ b/src/SourceFile.js @@ -3,7 +3,7 @@ import { Utils, Literal } from "@nodesecure/sec-literal"; import { VariableTracer } from "@nodesecure/estree-ast-utils"; // Import Internal Dependencies -import { rootLocation, toArrayLocation } from "./utils.js"; +import { rootLocation, toArrayLocation } from "./utils/index.js"; import { generateWarning } from "./warnings.js"; import { isObfuscatedCode, hasTrojanSource } from "./obfuscators/index.js"; import { ProbeRunner } from "./ProbeRunner.js"; diff --git a/src/obfuscators/jjencode.js b/src/obfuscators/jjencode.js index bf71020..740c48b 100644 --- a/src/obfuscators/jjencode.js +++ b/src/obfuscators/jjencode.js @@ -1,5 +1,5 @@ // Require Internal Dependencies -import { notNullOrUndefined } from "../utils.js"; +import { notNullOrUndefined } from "../utils/index.js"; // CONSTANTS const kJJRegularSymbols = new Set(["$", "_"]); diff --git a/src/probes/isArrayExpression.js b/src/probes/isArrayExpression.js index af2650e..c96cb94 100644 --- a/src/probes/isArrayExpression.js +++ b/src/probes/isArrayExpression.js @@ -1,5 +1,5 @@ // Import Internal Dependencies -import { extractNode } from "../utils.js"; +import { extractNode } from "../utils/index.js"; // CONSTANTS const kLiteralExtractor = extractNode("Literal"); diff --git a/src/probes/isClassDeclaration.js b/src/probes/isClassDeclaration.js index e2e6529..44e2a30 100644 --- a/src/probes/isClassDeclaration.js +++ b/src/probes/isClassDeclaration.js @@ -1,5 +1,5 @@ // Import Internal Dependencies -import { extractNode } from "../utils.js"; +import { extractNode } from "../utils/index.js"; // CONSTANTS const kIdExtractor = extractNode("Identifier"); diff --git a/src/probes/isFunction.js b/src/probes/isFunction.js index ef0dd07..d9eb7d7 100644 --- a/src/probes/isFunction.js +++ b/src/probes/isFunction.js @@ -1,5 +1,5 @@ // Import Internal Dependencies -import { extractNode } from "../utils.js"; +import { extractNode } from "../utils/index.js"; // CONSTANTS const kIdExtractor = extractNode("Identifier"); diff --git a/src/probes/isMethodDefinition.js b/src/probes/isMethodDefinition.js index 4585b50..284342c 100644 --- a/src/probes/isMethodDefinition.js +++ b/src/probes/isMethodDefinition.js @@ -1,5 +1,5 @@ // Import Internal Dependencies -import { extractNode } from "../utils.js"; +import { extractNode } from "../utils/index.js"; // CONSTANTS const kIdExtractor = extractNode("Identifier"); diff --git a/src/probes/isUnsafeCallee.js b/src/probes/isUnsafeCallee.js index 6a6ea0a..68a1aa9 100644 --- a/src/probes/isUnsafeCallee.js +++ b/src/probes/isUnsafeCallee.js @@ -1,5 +1,5 @@ // Import Internal Dependencies -import { isUnsafeCallee } from "../utils.js"; +import { isUnsafeCallee } from "../utils/index.js"; import { ProbeSignals } from "../ProbeRunner.js"; /** diff --git a/src/utils.js b/src/utils.js deleted file mode 100644 index 82d4f35..0000000 --- a/src/utils.js +++ /dev/null @@ -1,111 +0,0 @@ -// Import Third-party Dependencies -import { - getCallExpressionIdentifier -} from "@nodesecure/estree-ast-utils"; - -export function notNullOrUndefined(value) { - return value !== null && value !== void 0; -} - -function isEvalCallee(node) { - const identifier = getCallExpressionIdentifier(node, { - resolveCallExpression: false - }); - - return identifier === "eval"; -} - -function isFunctionCallee(node) { - const identifier = getCallExpressionIdentifier(node); - - return identifier === "Function" && node.callee.type === "CallExpression"; -} - -export function isUnsafeCallee(node) { - if (isEvalCallee(node)) { - return [true, "eval"]; - } - - if (isFunctionCallee(node)) { - return [true, "Function"]; - } - - return [false, null]; -} - -export function isOneLineExpressionExport(body) { - if (body.length > 1) { - return false; - } - - if (body[0].type !== "ExpressionStatement") { - return false; - } - - if (body[0].expression.type !== "AssignmentExpression") { - return false; - } - - return exportAssignmentHasRequireLeave(body[0].expression.right); -} - -export function exportAssignmentHasRequireLeave(expr) { - if (expr.type === "LogicalExpression") { - return atLeastOneBranchHasRequireLeave(expr.left, expr.right); - } - - if (expr.type === "ConditionalExpression") { - return atLeastOneBranchHasRequireLeave(expr.consequent, expr.alternate); - } - - if (expr.type === "CallExpression") { - return getCallExpressionIdentifier(expr) === "require"; - } - - if (expr.type === "MemberExpression") { - let rootMember = expr.object; - while (rootMember.type === "MemberExpression") { - rootMember = rootMember.object; - } - - if (rootMember.type !== "CallExpression") { - return false; - } - - return getCallExpressionIdentifier(rootMember) === "require"; - } - - return false; -} - -function atLeastOneBranchHasRequireLeave(left, right) { - return [ - exportAssignmentHasRequireLeave(left), - exportAssignmentHasRequireLeave(right) - ].some((hasRequire) => hasRequire); -} - -export function rootLocation() { - return { start: { line: 0, column: 0 }, end: { line: 0, column: 0 } }; -} - -export function toArrayLocation(location = rootLocation()) { - const { start, end = start } = location; - - return [ - [start.line || 0, start.column || 0], - [end.line || 0, end.column || 0] - ]; -} - -export function extractNode(expectedType) { - return (callback, nodes) => { - const finalNodes = Array.isArray(nodes) ? nodes : [nodes]; - - for (const node of finalNodes) { - if (notNullOrUndefined(node) && node.type === expectedType) { - callback(node); - } - } - }; -} diff --git a/src/utils/exportAssignmentHasRequireLeave.js b/src/utils/exportAssignmentHasRequireLeave.js new file mode 100644 index 0000000..9ef76ea --- /dev/null +++ b/src/utils/exportAssignmentHasRequireLeave.js @@ -0,0 +1,40 @@ +// Import Third-party Dependencies +import { + getCallExpressionIdentifier +} from "@nodesecure/estree-ast-utils"; + +export function exportAssignmentHasRequireLeave(expr) { + if (expr.type === "LogicalExpression") { + return atLeastOneBranchHasRequireLeave(expr.left, expr.right); + } + + if (expr.type === "ConditionalExpression") { + return atLeastOneBranchHasRequireLeave(expr.consequent, expr.alternate); + } + + if (expr.type === "CallExpression") { + return getCallExpressionIdentifier(expr) === "require"; + } + + if (expr.type === "MemberExpression") { + let rootMember = expr.object; + while (rootMember.type === "MemberExpression") { + rootMember = rootMember.object; + } + + if (rootMember.type !== "CallExpression") { + return false; + } + + return getCallExpressionIdentifier(rootMember) === "require"; + } + + return false; +} + +function atLeastOneBranchHasRequireLeave(left, right) { + return [ + exportAssignmentHasRequireLeave(left), + exportAssignmentHasRequireLeave(right) + ].some((hasRequire) => hasRequire); +} diff --git a/src/utils/extractNode.js b/src/utils/extractNode.js new file mode 100644 index 0000000..dba737d --- /dev/null +++ b/src/utils/extractNode.js @@ -0,0 +1,14 @@ +// Import Internal Dependencies +import { notNullOrUndefined } from "./notNullOrUndefined.js"; + +export function extractNode(expectedType) { + return (callback, nodes) => { + const finalNodes = Array.isArray(nodes) ? nodes : [nodes]; + + for (const node of finalNodes) { + if (notNullOrUndefined(node) && node.type === expectedType) { + callback(node); + } + } + }; +} diff --git a/src/utils/index.js b/src/utils/index.js new file mode 100644 index 0000000..9910987 --- /dev/null +++ b/src/utils/index.js @@ -0,0 +1,7 @@ +export * from "./exportAssignmentHasRequireLeave.js"; +export * from "./extractNode.js"; +export * from "./isOneLineExpressionExport.js"; +export * from "./isUnsafeCallee.js"; +export * from "./notNullOrUndefined.js"; +export * from "./rootLocation.js"; +export * from "./toArrayLocation.js"; diff --git a/src/utils/isOneLineExpressionExport.js b/src/utils/isOneLineExpressionExport.js new file mode 100644 index 0000000..3c133d8 --- /dev/null +++ b/src/utils/isOneLineExpressionExport.js @@ -0,0 +1,18 @@ +// Import Internal Dependencies +import { exportAssignmentHasRequireLeave } from "./exportAssignmentHasRequireLeave.js"; + +export function isOneLineExpressionExport(body) { + if (body.length > 1) { + return false; + } + + if (body[0].type !== "ExpressionStatement") { + return false; + } + + if (body[0].expression.type !== "AssignmentExpression") { + return false; + } + + return exportAssignmentHasRequireLeave(body[0].expression.right); +} diff --git a/src/utils/isUnsafeCallee.js b/src/utils/isUnsafeCallee.js new file mode 100644 index 0000000..6f611f4 --- /dev/null +++ b/src/utils/isUnsafeCallee.js @@ -0,0 +1,28 @@ +// Import Third-party Dependencies +import { getCallExpressionIdentifier } from "@nodesecure/estree-ast-utils"; + +function isEvalCallee(node) { + const identifier = getCallExpressionIdentifier(node, { + resolveCallExpression: false + }); + + return identifier === "eval"; +} + +function isFunctionCallee(node) { + const identifier = getCallExpressionIdentifier(node); + + return identifier === "Function" && node.callee.type === "CallExpression"; +} + +export function isUnsafeCallee(node) { + if (isEvalCallee(node)) { + return [true, "eval"]; + } + + if (isFunctionCallee(node)) { + return [true, "Function"]; + } + + return [false, null]; +} diff --git a/src/utils/notNullOrUndefined.js b/src/utils/notNullOrUndefined.js new file mode 100644 index 0000000..9eee585 --- /dev/null +++ b/src/utils/notNullOrUndefined.js @@ -0,0 +1,3 @@ +export function notNullOrUndefined(value) { + return value !== null && value !== void 0; +} diff --git a/src/utils/rootLocation.js b/src/utils/rootLocation.js new file mode 100644 index 0000000..8d6275a --- /dev/null +++ b/src/utils/rootLocation.js @@ -0,0 +1,3 @@ +export function rootLocation() { + return { start: { line: 0, column: 0 }, end: { line: 0, column: 0 } }; +} diff --git a/src/utils/toArrayLocation.js b/src/utils/toArrayLocation.js new file mode 100644 index 0000000..6eedfe6 --- /dev/null +++ b/src/utils/toArrayLocation.js @@ -0,0 +1,11 @@ +// Import Internal Dependencies +import { rootLocation } from "./rootLocation.js"; + +export function toArrayLocation(location = rootLocation()) { + const { start, end = start } = location; + + return [ + [start.line || 0, start.column || 0], + [end.line || 0, end.column || 0] + ]; +} diff --git a/src/warnings.js b/src/warnings.js index 7faa619..e80b110 100644 --- a/src/warnings.js +++ b/src/warnings.js @@ -1,5 +1,5 @@ // Import Internal Dependencies -import * as utils from "./utils.js"; +import * as utils from "./utils/index.js"; export const warnings = Object.freeze({ "parsing-error": { diff --git a/test/warnings.spec.js b/test/warnings.spec.js index 2c26ed8..c59db32 100644 --- a/test/warnings.spec.js +++ b/test/warnings.spec.js @@ -3,7 +3,7 @@ import { test } from "node:test"; import assert from "node:assert"; // Import Internal Dependencies -import { rootLocation } from "../src/utils.js"; +import { rootLocation } from "../src/utils/index.js"; import { generateWarning } from "../src/warnings.js"; test("Given an encoded-literal kind it should generate a warning with deep location array", () => {