@coana-tech/cli 14.12.122 → 14.12.124
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli.mjs +1 -1
- package/package.json +1 -1
- package/reachability-analyzers-cli.mjs +1 -0
- package/repos/coana-tech/goana/bin/goana-darwin-amd64.gz +0 -0
- package/repos/coana-tech/goana/bin/goana-darwin-arm64.gz +0 -0
- package/repos/coana-tech/goana/bin/goana-linux-amd64.gz +0 -0
- package/repos/coana-tech/goana/bin/goana-linux-arm64.gz +0 -0
- package/repos/coana-tech/javap-service/javap-service.jar +0 -0
- package/repos/coana-tech/jelly-private/dist/bundle/approx.js +3 -3
- package/repos/coana-tech/jelly-private/dist/bundle/{chunk-RUAUP2X2.js → chunk-D4F3MOY5.js} +2 -2
- package/repos/coana-tech/jelly-private/dist/bundle/{chunk-XXE5Z2AZ.js → chunk-L7Z5ACXW.js} +2 -2
- package/repos/coana-tech/jelly-private/dist/bundle/{chunk-US4VPHJ4.js → chunk-NNOCQRBG.js} +34 -4
- package/repos/coana-tech/jelly-private/dist/bundle/{chunk-VENMYXZQ.js → chunk-XK6IPQRH.js} +2 -2
- package/repos/coana-tech/jelly-private/dist/bundle/hooks.js +3 -3
- package/repos/coana-tech/jelly-private/dist/bundle/jelly.js +603 -161
package/cli.mjs
CHANGED
|
@@ -251019,7 +251019,7 @@ async function onlineScan(dependencyTree, apiKey, timeout) {
|
|
|
251019
251019
|
}
|
|
251020
251020
|
|
|
251021
251021
|
// dist/version.js
|
|
251022
|
-
var version3 = "14.12.
|
|
251022
|
+
var version3 = "14.12.124";
|
|
251023
251023
|
|
|
251024
251024
|
// dist/cli-core.js
|
|
251025
251025
|
var { mapValues, omit, partition, pickBy: pickBy2 } = import_lodash15.default;
|
package/package.json
CHANGED
|
@@ -110410,6 +110410,7 @@ async function runJellyAnalysis(mainProjectRoot, projectRoot, jellyOptions, reac
|
|
|
110410
110410
|
--basedir ${mainProjectRoot}
|
|
110411
110411
|
--timeout ${timeoutInSeconds}
|
|
110412
110412
|
--vulnerabilities ${vulnerabilitiesFile}
|
|
110413
|
+
${experiment === "LAZY_EXPERIMENT" && ["--lazy", "--lazy-cleanup"]}
|
|
110413
110414
|
--reachable-json ${affectedPackagesFile}
|
|
110414
110415
|
${getExcludes(mainProjectRoot, projectRoot, reachabilityAnalysisOptions)}
|
|
110415
110416
|
--diagnostics-json ${diagnosticsFile}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -7,11 +7,11 @@ import "./iterator-helpers-polyfill.js";
|
|
|
7
7
|
import {
|
|
8
8
|
require_hints,
|
|
9
9
|
require_parser
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-D4F3MOY5.js";
|
|
11
11
|
import {
|
|
12
12
|
require_proxy,
|
|
13
13
|
require_sandbox
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-XK6IPQRH.js";
|
|
15
15
|
import {
|
|
16
16
|
__commonJS,
|
|
17
17
|
__name,
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
require_options,
|
|
22
22
|
require_transform,
|
|
23
23
|
require_util
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-NNOCQRBG.js";
|
|
25
25
|
|
|
26
26
|
// lib/approx/approx.js
|
|
27
27
|
var require_approx = __commonJS({
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
require_options,
|
|
15
15
|
require_tokens,
|
|
16
16
|
require_util
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-NNOCQRBG.js";
|
|
18
18
|
|
|
19
19
|
// lib/parsing/parser.js
|
|
20
20
|
var require_parser = __commonJS({
|
|
@@ -516,4 +516,4 @@ export {
|
|
|
516
516
|
require_patching,
|
|
517
517
|
require_hints
|
|
518
518
|
};
|
|
519
|
-
//# sourceMappingURL=chunk-
|
|
519
|
+
//# sourceMappingURL=chunk-D4F3MOY5.js.map
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
__commonJS,
|
|
9
9
|
__name,
|
|
10
10
|
__require
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-NNOCQRBG.js";
|
|
12
12
|
|
|
13
13
|
// node_modules/source-map/lib/base64.js
|
|
14
14
|
var require_base64 = __commonJS({
|
|
@@ -224380,4 +224380,4 @@ typescript/lib/typescript.js:
|
|
|
224380
224380
|
and limitations under the License.
|
|
224381
224381
|
***************************************************************************** *)
|
|
224382
224382
|
*/
|
|
224383
|
-
//# sourceMappingURL=chunk-
|
|
224383
|
+
//# sourceMappingURL=chunk-L7Z5ACXW.js.map
|
|
@@ -74,6 +74,7 @@ var require_package = __commonJS({
|
|
|
74
74
|
"@babel/traverse": "^7.28.5",
|
|
75
75
|
"@babel/types": "^7.28.5",
|
|
76
76
|
commander: "^9.5.0",
|
|
77
|
+
lodash: "^4.17.21",
|
|
77
78
|
micromatch: "^4.0.8",
|
|
78
79
|
semver: "^7.7.3",
|
|
79
80
|
stringify2stream: "^1.1.0",
|
|
@@ -88,10 +89,12 @@ var require_package = __commonJS({
|
|
|
88
89
|
"@types/node": "^24.10.1",
|
|
89
90
|
"@types/semver": "^7.7.1",
|
|
90
91
|
esbuild: "^0.25.9",
|
|
92
|
+
"fast-check": "^4.2.0",
|
|
91
93
|
jest: "^30.2.0",
|
|
92
94
|
"jest-expect-message": "^1.1.3",
|
|
95
|
+
tar: "^7.4.3",
|
|
93
96
|
"ts-jest": "^29.4.6",
|
|
94
|
-
|
|
97
|
+
tsx: "^4.0.0"
|
|
95
98
|
},
|
|
96
99
|
pkg: {
|
|
97
100
|
targets: [
|
|
@@ -10868,7 +10871,9 @@ var require_options = __commonJS({
|
|
|
10868
10871
|
reachableJson: void 0,
|
|
10869
10872
|
callstacksJson: void 0,
|
|
10870
10873
|
vulnerabilitiesFull: false,
|
|
10871
|
-
modulesJson: void 0
|
|
10874
|
+
modulesJson: void 0,
|
|
10875
|
+
lazy: false,
|
|
10876
|
+
lazyCleanup: false
|
|
10872
10877
|
};
|
|
10873
10878
|
function setOptions(opts) {
|
|
10874
10879
|
for (const opt of Object.getOwnPropertyNames(exports.options)) {
|
|
@@ -10952,6 +10957,7 @@ var require_util = __commonJS({
|
|
|
10952
10957
|
exports.strHash = strHash;
|
|
10953
10958
|
exports.isArrayIndex = isArrayIndex;
|
|
10954
10959
|
exports.percent = percent;
|
|
10960
|
+
exports.getReverseGraph = getReverseGraph;
|
|
10955
10961
|
exports.mapCallsToFunctions = mapCallsToFunctions;
|
|
10956
10962
|
exports.longestCommonPrefix = longestCommonPrefix;
|
|
10957
10963
|
exports.stringify = stringify;
|
|
@@ -11242,6 +11248,15 @@ var require_util = __commonJS({
|
|
|
11242
11248
|
return `${(100 * x).toFixed(2)}%`;
|
|
11243
11249
|
}
|
|
11244
11250
|
__name(percent, "percent");
|
|
11251
|
+
function getReverseGraph(g) {
|
|
11252
|
+
const r = /* @__PURE__ */ new Map();
|
|
11253
|
+
for (const [from, tos] of g)
|
|
11254
|
+
if (tos?.size)
|
|
11255
|
+
for (const to of tos)
|
|
11256
|
+
mapGetSet(r, to).add(from);
|
|
11257
|
+
return r;
|
|
11258
|
+
}
|
|
11259
|
+
__name(getReverseGraph, "getReverseGraph");
|
|
11245
11260
|
var SourceLocationsToJSON = class {
|
|
11246
11261
|
static {
|
|
11247
11262
|
__name(this, "SourceLocationsToJSON");
|
|
@@ -13627,6 +13642,7 @@ var require_infos = __commonJS({
|
|
|
13627
13642
|
isIncluded;
|
|
13628
13643
|
functions = /* @__PURE__ */ new Set();
|
|
13629
13644
|
loc;
|
|
13645
|
+
ast;
|
|
13630
13646
|
hash;
|
|
13631
13647
|
directDependents = /* @__PURE__ */ new Set();
|
|
13632
13648
|
constructor(relativePath, packageInfo, isEntry, isIncluded) {
|
|
@@ -13698,7 +13714,7 @@ var require_accesspaths = __commonJS({
|
|
|
13698
13714
|
"lib/analysis/accesspaths.js"(exports) {
|
|
13699
13715
|
"use strict";
|
|
13700
13716
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13701
|
-
exports.UnknownAccessPath = exports.IgnoredAccessPath = exports.ComponentAccessPath = exports.CallResultAccessPath = exports.PropertyAccessPath = exports.ModuleAccessPath = exports.AccessPath = void 0;
|
|
13717
|
+
exports.LazyAccessPath = exports.UnknownAccessPath = exports.IgnoredAccessPath = exports.ComponentAccessPath = exports.CallResultAccessPath = exports.PropertyAccessPath = exports.ModuleAccessPath = exports.AccessPath = void 0;
|
|
13702
13718
|
var infos_1 = require_infos();
|
|
13703
13719
|
var AccessPath = class {
|
|
13704
13720
|
static {
|
|
@@ -13782,6 +13798,19 @@ var require_accesspaths = __commonJS({
|
|
|
13782
13798
|
}
|
|
13783
13799
|
};
|
|
13784
13800
|
exports.UnknownAccessPath = UnknownAccessPath;
|
|
13801
|
+
var LazyAccessPath = class extends AccessPath {
|
|
13802
|
+
static {
|
|
13803
|
+
__name(this, "LazyAccessPath");
|
|
13804
|
+
}
|
|
13805
|
+
moduleInfo;
|
|
13806
|
+
dependents;
|
|
13807
|
+
constructor(moduleInfo, dependents) {
|
|
13808
|
+
super(`${dependents ? "<<" : ">>"}${moduleInfo}`);
|
|
13809
|
+
this.moduleInfo = moduleInfo;
|
|
13810
|
+
this.dependents = dependents;
|
|
13811
|
+
}
|
|
13812
|
+
};
|
|
13813
|
+
exports.LazyAccessPath = LazyAccessPath;
|
|
13785
13814
|
}
|
|
13786
13815
|
});
|
|
13787
13816
|
|
|
@@ -13831,6 +13860,7 @@ var require_astvisitor = __commonJS({
|
|
|
13831
13860
|
const fun = (0, asthelpers_1.getEnclosingNonArrowFunction)(path);
|
|
13832
13861
|
if (fun) {
|
|
13833
13862
|
solver.addSubsetConstraint(vp.thisVar(fun), vp.nodeVar(path.node));
|
|
13863
|
+
f.registerThis(fun);
|
|
13834
13864
|
} else {
|
|
13835
13865
|
solver.addTokenConstraint(op.exportsObjectToken, vp.nodeVar(path.node));
|
|
13836
13866
|
}
|
|
@@ -19839,4 +19869,4 @@ fill-range/index.js:
|
|
|
19839
19869
|
* Licensed under the MIT License.
|
|
19840
19870
|
*)
|
|
19841
19871
|
*/
|
|
19842
|
-
//# sourceMappingURL=chunk-
|
|
19872
|
+
//# sourceMappingURL=chunk-NNOCQRBG.js.map
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
__name,
|
|
10
10
|
__require,
|
|
11
11
|
require_transform
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-NNOCQRBG.js";
|
|
13
13
|
|
|
14
14
|
// lib/approx/proxy.js
|
|
15
15
|
var require_proxy = __commonJS({
|
|
@@ -268,4 +268,4 @@ export {
|
|
|
268
268
|
require_proxy,
|
|
269
269
|
require_sandbox
|
|
270
270
|
};
|
|
271
|
-
//# sourceMappingURL=chunk-
|
|
271
|
+
//# sourceMappingURL=chunk-XK6IPQRH.js.map
|
|
@@ -6,10 +6,10 @@ import "./iterator-helpers-polyfill.js";
|
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
8
|
require_moduleresolver
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-L7Z5ACXW.js";
|
|
10
10
|
import {
|
|
11
11
|
require_sandbox
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-XK6IPQRH.js";
|
|
13
13
|
import {
|
|
14
14
|
__commonJS,
|
|
15
15
|
__name,
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
require_files,
|
|
18
18
|
require_options,
|
|
19
19
|
require_transform
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-NNOCQRBG.js";
|
|
21
21
|
|
|
22
22
|
// lib/approx/hooks.js
|
|
23
23
|
var require_hooks = __commonJS({
|
|
@@ -9,11 +9,11 @@ import {
|
|
|
9
9
|
require_hints,
|
|
10
10
|
require_parser,
|
|
11
11
|
require_patching
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-D4F3MOY5.js";
|
|
13
13
|
import {
|
|
14
14
|
require_moduleresolver,
|
|
15
15
|
require_typescript
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-L7Z5ACXW.js";
|
|
17
17
|
import {
|
|
18
18
|
__commonJS,
|
|
19
19
|
__name,
|
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
require_tokens,
|
|
38
38
|
require_transform,
|
|
39
39
|
require_util
|
|
40
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-NNOCQRBG.js";
|
|
41
41
|
|
|
42
42
|
// lib/misc/timer.js
|
|
43
43
|
var require_timer = __commonJS({
|
|
@@ -177,6 +177,8 @@ var require_globalstate = __commonJS({
|
|
|
177
177
|
entryFiles = /* @__PURE__ */ new Set();
|
|
178
178
|
reachedFiles = /* @__PURE__ */ new Set();
|
|
179
179
|
pendingFiles = new worklist_1.Worklist();
|
|
180
|
+
reachedModulesFull = /* @__PURE__ */ new Set();
|
|
181
|
+
pendingModulesFull = new worklist_1.Worklist();
|
|
180
182
|
filesWithParseErrors = [];
|
|
181
183
|
filesAnalyzed = [];
|
|
182
184
|
timeoutTimer = new timer_1.default();
|
|
@@ -257,6 +259,18 @@ var require_globalstate = __commonJS({
|
|
|
257
259
|
(parent ? this.functionInfos.get(parent).functions : m.functions).add(f);
|
|
258
260
|
this.vulnerabilities?.reachedFunction(f);
|
|
259
261
|
}
|
|
262
|
+
reachedModuleFull(m) {
|
|
263
|
+
if (!m.isIncluded)
|
|
264
|
+
assert_1.default.fail(`Module ${m} is not included in the analysis!`);
|
|
265
|
+
if (options_1.options.modulesOnly)
|
|
266
|
+
assert_1.default.fail("reachedModuleFull called in modulesOnly mode!");
|
|
267
|
+
if (!this.reachedModulesFull.has(m)) {
|
|
268
|
+
if (options_1.options.lazy && logger_1.default.isVerboseEnabled())
|
|
269
|
+
logger_1.default.verbose(`Lazy: Module ${m} added for full analysis`);
|
|
270
|
+
this.reachedModulesFull.add(m);
|
|
271
|
+
this.pendingModulesFull.enqueue(m);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
260
274
|
reachedFile(tofile, entry, from, local) {
|
|
261
275
|
let moduleInfo;
|
|
262
276
|
if (this.reachedFiles.has(tofile))
|
|
@@ -484,6 +498,7 @@ var require_fragmentstate = __commonJS({
|
|
|
484
498
|
numberOfFunctionToFunctionEdges = 0;
|
|
485
499
|
numberOfCallToFunctionEdges = 0;
|
|
486
500
|
functionsWithArguments = /* @__PURE__ */ new Set();
|
|
501
|
+
functionsWithThis = /* @__PURE__ */ new Set();
|
|
487
502
|
artificialFunctions = [];
|
|
488
503
|
callLocations = /* @__PURE__ */ new Set();
|
|
489
504
|
nativeCallLocations = /* @__PURE__ */ new Set();
|
|
@@ -510,6 +525,7 @@ var require_fragmentstate = __commonJS({
|
|
|
510
525
|
dynamicPropertyWrites = /* @__PURE__ */ new Set();
|
|
511
526
|
maybeEmptyMethodCalls = /* @__PURE__ */ new Map();
|
|
512
527
|
functionTokens = /* @__PURE__ */ new Set();
|
|
528
|
+
lazyEscaping = /* @__PURE__ */ new Map();
|
|
513
529
|
constructor(s) {
|
|
514
530
|
this.a = s.globalState;
|
|
515
531
|
this.varProducer = new constraintvarproducer_1.ConstraintVarProducer(s, s.globalState);
|
|
@@ -654,6 +670,11 @@ var require_fragmentstate = __commonJS({
|
|
|
654
670
|
}
|
|
655
671
|
return f;
|
|
656
672
|
}
|
|
673
|
+
registerThis(f) {
|
|
674
|
+
this.functionsWithThis.add(f);
|
|
675
|
+
if (logger_1.default.isDebugEnabled())
|
|
676
|
+
logger_1.default.debug(`Function uses 'this': ${(0, util_1.locationToStringWithFile)(f.loc)}`);
|
|
677
|
+
}
|
|
657
678
|
getRepresentative(v) {
|
|
658
679
|
let w = v;
|
|
659
680
|
const ws = [];
|
|
@@ -661,7 +682,7 @@ var require_fragmentstate = __commonJS({
|
|
|
661
682
|
const w2 = this.redirections.get(w);
|
|
662
683
|
if (!w2)
|
|
663
684
|
break;
|
|
664
|
-
(0, assert_1.default)(ws.length <
|
|
685
|
+
(0, assert_1.default)(ws.length < 1e3);
|
|
665
686
|
ws.push(w);
|
|
666
687
|
w = w2;
|
|
667
688
|
}
|
|
@@ -986,6 +1007,7 @@ var require_diagnostics = __commonJS({
|
|
|
986
1007
|
}
|
|
987
1008
|
packages = 0;
|
|
988
1009
|
modules = 0;
|
|
1010
|
+
modulesFull = 0;
|
|
989
1011
|
functions = 0;
|
|
990
1012
|
vars = 0;
|
|
991
1013
|
listeners = 0;
|
|
@@ -1016,6 +1038,7 @@ var require_diagnostics = __commonJS({
|
|
|
1016
1038
|
unprocessedTokensSize = 0;
|
|
1017
1039
|
wave = 0;
|
|
1018
1040
|
round = 0;
|
|
1041
|
+
analyzerRounds = 0;
|
|
1019
1042
|
listenerNotificationRounds = 0;
|
|
1020
1043
|
lastPrintDiagnosticsTime = 0;
|
|
1021
1044
|
tokenListenerNotifications = 0;
|
|
@@ -1043,6 +1066,323 @@ var require_diagnostics = __commonJS({
|
|
|
1043
1066
|
}
|
|
1044
1067
|
});
|
|
1045
1068
|
|
|
1069
|
+
// lib/misc/bitset.js
|
|
1070
|
+
var require_bitset = __commonJS({
|
|
1071
|
+
"lib/misc/bitset.js"(exports) {
|
|
1072
|
+
"use strict";
|
|
1073
|
+
var __importDefault = exports && exports.__importDefault || function(mod) {
|
|
1074
|
+
return mod && mod.__esModule ? mod : { "default": mod };
|
|
1075
|
+
};
|
|
1076
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1077
|
+
exports.BitSet = void 0;
|
|
1078
|
+
var node_assert_1 = __importDefault(__require("node:assert"));
|
|
1079
|
+
var BitSet = class {
|
|
1080
|
+
static {
|
|
1081
|
+
__name(this, "BitSet");
|
|
1082
|
+
}
|
|
1083
|
+
static make(size) {
|
|
1084
|
+
if (size <= 32)
|
|
1085
|
+
return new SmallBitSet();
|
|
1086
|
+
return new LargeBitSet(size);
|
|
1087
|
+
}
|
|
1088
|
+
};
|
|
1089
|
+
exports.BitSet = BitSet;
|
|
1090
|
+
var SmallBitSet = class _SmallBitSet extends BitSet {
|
|
1091
|
+
static {
|
|
1092
|
+
__name(this, "SmallBitSet");
|
|
1093
|
+
}
|
|
1094
|
+
v = 0;
|
|
1095
|
+
get value() {
|
|
1096
|
+
return this.v;
|
|
1097
|
+
}
|
|
1098
|
+
isEmpty() {
|
|
1099
|
+
return !this.v;
|
|
1100
|
+
}
|
|
1101
|
+
set(index) {
|
|
1102
|
+
if (index < 0 || index >= 32)
|
|
1103
|
+
throw new RangeError(`Index out of bounds: ${index}`);
|
|
1104
|
+
this.v |= 1 << index;
|
|
1105
|
+
}
|
|
1106
|
+
unionUpdate(other) {
|
|
1107
|
+
(0, node_assert_1.default)(other instanceof _SmallBitSet, "Expected other to be SmallBitSet");
|
|
1108
|
+
this.v |= other.v;
|
|
1109
|
+
}
|
|
1110
|
+
*[Symbol.iterator]() {
|
|
1111
|
+
let { v } = this;
|
|
1112
|
+
for (let i = 0; v; i++, v >>>= 1)
|
|
1113
|
+
if (v & 1)
|
|
1114
|
+
yield i;
|
|
1115
|
+
}
|
|
1116
|
+
};
|
|
1117
|
+
var LargeBitSet = class _LargeBitSet extends BitSet {
|
|
1118
|
+
static {
|
|
1119
|
+
__name(this, "LargeBitSet");
|
|
1120
|
+
}
|
|
1121
|
+
size;
|
|
1122
|
+
words;
|
|
1123
|
+
empty = true;
|
|
1124
|
+
constructor(size) {
|
|
1125
|
+
super();
|
|
1126
|
+
this.size = size;
|
|
1127
|
+
this.words = new Int32Array(size + 31 >>> 5);
|
|
1128
|
+
}
|
|
1129
|
+
isEmpty() {
|
|
1130
|
+
return this.empty;
|
|
1131
|
+
}
|
|
1132
|
+
set(index) {
|
|
1133
|
+
if (index < 0 || index >= this.size)
|
|
1134
|
+
throw new RangeError(`Index out of bounds: ${index}`);
|
|
1135
|
+
this.words[index >>> 5] |= 1 << (index & 31);
|
|
1136
|
+
this.empty = false;
|
|
1137
|
+
}
|
|
1138
|
+
unionUpdate(other) {
|
|
1139
|
+
if (other instanceof SmallBitSet) {
|
|
1140
|
+
this.words[0] |= other.value;
|
|
1141
|
+
this.empty &&= other.isEmpty();
|
|
1142
|
+
} else {
|
|
1143
|
+
(0, node_assert_1.default)(other instanceof _LargeBitSet, "Expected other to be LargeBitSet");
|
|
1144
|
+
node_assert_1.default.strictEqual(this.size, other.size, "BitSets must have same size");
|
|
1145
|
+
for (const [i, w] of other.words.entries())
|
|
1146
|
+
this.words[i] |= w;
|
|
1147
|
+
this.empty &&= other.empty;
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
*[Symbol.iterator]() {
|
|
1151
|
+
for (let [wi, w] of this.words.entries()) {
|
|
1152
|
+
if (!w)
|
|
1153
|
+
continue;
|
|
1154
|
+
const baseIndex = wi << 5;
|
|
1155
|
+
for (let i = 0; w; i++, w >>>= 1) {
|
|
1156
|
+
if (w & 1)
|
|
1157
|
+
yield baseIndex + i;
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
};
|
|
1162
|
+
}
|
|
1163
|
+
});
|
|
1164
|
+
|
|
1165
|
+
// lib/analysis/escaping.js
|
|
1166
|
+
var require_escaping = __commonJS({
|
|
1167
|
+
"lib/analysis/escaping.js"(exports) {
|
|
1168
|
+
"use strict";
|
|
1169
|
+
var __importDefault = exports && exports.__importDefault || function(mod) {
|
|
1170
|
+
return mod && mod.__esModule ? mod : { "default": mod };
|
|
1171
|
+
};
|
|
1172
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1173
|
+
exports.findEscapingObjects = findEscapingObjects;
|
|
1174
|
+
exports.findExportedTokens = findExportedTokens;
|
|
1175
|
+
var tokens_1 = require_tokens();
|
|
1176
|
+
var constraintvars_1 = require_constraintvars();
|
|
1177
|
+
var logger_1 = __importDefault(require_logger());
|
|
1178
|
+
var types_1 = __require("@babel/types");
|
|
1179
|
+
var accesspaths_1 = require_accesspaths();
|
|
1180
|
+
var ecmascript_1 = require_ecmascript();
|
|
1181
|
+
var options_1 = require_options();
|
|
1182
|
+
var packagejson_1 = require_packagejson();
|
|
1183
|
+
function findEscapingObjects(ms, solver) {
|
|
1184
|
+
const a = solver.globalState;
|
|
1185
|
+
const f = solver.fragmentState;
|
|
1186
|
+
const worklist = [];
|
|
1187
|
+
const visited = /* @__PURE__ */ new Set();
|
|
1188
|
+
const escaping = /* @__PURE__ */ new Set();
|
|
1189
|
+
const theUnknownAccessPathToken = a.canonicalizeToken(new tokens_1.AccessPathToken(accesspaths_1.UnknownAccessPath.instance));
|
|
1190
|
+
function addToWorklist(v) {
|
|
1191
|
+
for (const t of v instanceof tokens_1.Token ? [v] : f.getTokens(f.getRepresentative(v)))
|
|
1192
|
+
if ((t instanceof tokens_1.AllocationSiteToken || t instanceof tokens_1.FunctionToken || t instanceof tokens_1.NativeObjectToken && t.name === "exports") && !visited.has(t)) {
|
|
1193
|
+
worklist.push(t);
|
|
1194
|
+
visited.add(t);
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
__name(addToWorklist, "addToWorklist");
|
|
1198
|
+
for (const m of Array.isArray(ms) ? ms : [ms])
|
|
1199
|
+
if (1) {
|
|
1200
|
+
const pi = a.packageJsonInfos.get(m.packageInfo.dir);
|
|
1201
|
+
if (!pi?.exports || (0, packagejson_1.isInExports)(`./${m.relativePath}`, pi.exports))
|
|
1202
|
+
addToWorklist(f.varProducer.objPropVar(a.canonicalizeToken(new tokens_1.NativeObjectToken("module", m)), "exports"));
|
|
1203
|
+
}
|
|
1204
|
+
const w2 = [];
|
|
1205
|
+
while (worklist.length !== 0) {
|
|
1206
|
+
const t = worklist.pop();
|
|
1207
|
+
if (t instanceof tokens_1.FunctionToken)
|
|
1208
|
+
w2.push(t);
|
|
1209
|
+
else if (t instanceof tokens_1.ObjectToken || t instanceof tokens_1.NativeObjectToken && t.name === "exports") {
|
|
1210
|
+
for (const p of f.objectProperties.get(t) ?? [])
|
|
1211
|
+
if (!(0, ecmascript_1.isInternalProperty)(p))
|
|
1212
|
+
addToWorklist(f.varProducer.objPropVar(t, p));
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
visited.clear();
|
|
1216
|
+
for (const t of w2) {
|
|
1217
|
+
visited.add(t);
|
|
1218
|
+
worklist.push(t);
|
|
1219
|
+
}
|
|
1220
|
+
for (const v of f.maybeEscaping)
|
|
1221
|
+
addToWorklist(v);
|
|
1222
|
+
f.maybeEscaping.clear();
|
|
1223
|
+
while (worklist.length !== 0) {
|
|
1224
|
+
const t = worklist.pop();
|
|
1225
|
+
if (t instanceof tokens_1.ObjectToken) {
|
|
1226
|
+
if (logger_1.default.isDebugEnabled())
|
|
1227
|
+
logger_1.default.debug(`Escaping object: ${t}`);
|
|
1228
|
+
escaping.add(t);
|
|
1229
|
+
}
|
|
1230
|
+
if (t instanceof tokens_1.FunctionToken) {
|
|
1231
|
+
addToWorklist(f.varProducer.returnVar(t.fun));
|
|
1232
|
+
const tv = f.getRepresentative(f.varProducer.thisVar(t.fun));
|
|
1233
|
+
if (Array.from(f.getTokens(tv)).every((y) => !(0, constraintvars_1.isObjectPropertyVarObj)(y)) && ((0, types_1.isClassMethod)(t.fun) ? t.fun.kind === "constructor" : f.functionsWithThis.has(t.fun))) {
|
|
1234
|
+
const q = a.canonicalizeToken(new tokens_1.ObjectToken(t.fun));
|
|
1235
|
+
solver.addToken(q, tv);
|
|
1236
|
+
solver.addInherits(q, solver.varProducer.objPropVar(t, "prototype"));
|
|
1237
|
+
}
|
|
1238
|
+
for (const param of t.fun.params)
|
|
1239
|
+
if ((0, types_1.isIdentifier)(param))
|
|
1240
|
+
solver.addToken(theUnknownAccessPathToken, f.getRepresentative(f.varProducer.nodeVar(param)));
|
|
1241
|
+
solver.addToken(theUnknownAccessPathToken, f.getRepresentative(f.varProducer.thisVar(t.fun)));
|
|
1242
|
+
}
|
|
1243
|
+
for (const p of f.objectProperties.get(t) ?? [])
|
|
1244
|
+
if (!(0, ecmascript_1.isInternalProperty)(p)) {
|
|
1245
|
+
const w = f.varProducer.objPropVar(t, p);
|
|
1246
|
+
addToWorklist(w);
|
|
1247
|
+
solver.addToken(theUnknownAccessPathToken, f.getRepresentative(w));
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
if (logger_1.default.isVerboseEnabled()) {
|
|
1251
|
+
const objecttokens = /* @__PURE__ */ new Set();
|
|
1252
|
+
for (const [, ts] of f.getAllVarsAndTokens())
|
|
1253
|
+
for (const t of ts)
|
|
1254
|
+
if (t instanceof tokens_1.ObjectToken)
|
|
1255
|
+
objecttokens.add(t);
|
|
1256
|
+
logger_1.default.verbose(`Escaping objects: ${escaping.size}/${objecttokens.size}`);
|
|
1257
|
+
}
|
|
1258
|
+
return escaping;
|
|
1259
|
+
}
|
|
1260
|
+
__name(findEscapingObjects, "findEscapingObjects");
|
|
1261
|
+
function findExportedTokens(m, solver) {
|
|
1262
|
+
const a = solver.globalState;
|
|
1263
|
+
const f = solver.fragmentState;
|
|
1264
|
+
const vp = f.varProducer;
|
|
1265
|
+
return f.getTokens(f.getRepresentative(vp.objPropVar(a.canonicalizeToken(new tokens_1.NativeObjectToken("module", m)), "exports")));
|
|
1266
|
+
}
|
|
1267
|
+
__name(findExportedTokens, "findExportedTokens");
|
|
1268
|
+
}
|
|
1269
|
+
});
|
|
1270
|
+
|
|
1271
|
+
// lib/analysis/lazy.js
|
|
1272
|
+
var require_lazy = __commonJS({
|
|
1273
|
+
"lib/analysis/lazy.js"(exports) {
|
|
1274
|
+
"use strict";
|
|
1275
|
+
var __importDefault = exports && exports.__importDefault || function(mod) {
|
|
1276
|
+
return mod && mod.__esModule ? mod : { "default": mod };
|
|
1277
|
+
};
|
|
1278
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1279
|
+
exports.constructTokenReachabilityGraph = constructTokenReachabilityGraph;
|
|
1280
|
+
exports.isLazyAPActive = isLazyAPActive;
|
|
1281
|
+
exports.assertLazyAPActive = assertLazyAPActive;
|
|
1282
|
+
exports.getExportedFunctionsByModule = getExportedFunctionsByModule;
|
|
1283
|
+
var node_assert_1 = __importDefault(__require("node:assert"));
|
|
1284
|
+
var bitset_1 = require_bitset();
|
|
1285
|
+
var scc_1 = require_scc();
|
|
1286
|
+
var util_1 = require_util();
|
|
1287
|
+
var ecmascript_1 = require_ecmascript();
|
|
1288
|
+
var constraintvars_1 = require_constraintvars();
|
|
1289
|
+
var escaping_1 = require_escaping();
|
|
1290
|
+
var tokens_1 = require_tokens();
|
|
1291
|
+
var logger_1 = __importDefault(require_logger());
|
|
1292
|
+
function constructTokenReachabilityGraph(ts, solver) {
|
|
1293
|
+
const f = solver.fragmentState;
|
|
1294
|
+
const vp = f.varProducer;
|
|
1295
|
+
const worklist = [...ts];
|
|
1296
|
+
const graph = new Map(worklist.map((t) => [t, void 0]));
|
|
1297
|
+
const add = /* @__PURE__ */ __name((edges, v) => {
|
|
1298
|
+
for (const t of f.getTokens(f.getRepresentative(v))) {
|
|
1299
|
+
edges.add(t);
|
|
1300
|
+
if (!graph.has(t)) {
|
|
1301
|
+
graph.set(t, void 0);
|
|
1302
|
+
worklist.push(t);
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1305
|
+
}, "add");
|
|
1306
|
+
let anyFunction = false;
|
|
1307
|
+
while (worklist.length !== 0) {
|
|
1308
|
+
const t = worklist.pop();
|
|
1309
|
+
if ((0, constraintvars_1.isObjectPropertyVarObj)(t)) {
|
|
1310
|
+
const edges = /* @__PURE__ */ new Set();
|
|
1311
|
+
graph.set(t, edges);
|
|
1312
|
+
for (const p of f.objectProperties.get(t) ?? [])
|
|
1313
|
+
if (p !== ecmascript_1.ARRAY_ALL)
|
|
1314
|
+
for (const ac of ["normal", "get", "set"])
|
|
1315
|
+
add(edges, vp.objPropVar(t, p, ac));
|
|
1316
|
+
if (t instanceof tokens_1.FunctionToken) {
|
|
1317
|
+
anyFunction = true;
|
|
1318
|
+
add(edges, vp.returnVar(t.fun));
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
return [graph, anyFunction];
|
|
1323
|
+
}
|
|
1324
|
+
__name(constructTokenReachabilityGraph, "constructTokenReachabilityGraph");
|
|
1325
|
+
function isLazyAPActive(ap, a) {
|
|
1326
|
+
if (ap.dependents) {
|
|
1327
|
+
return ap.moduleInfo.directDependents.values().some((m) => !a.reachedModulesFull.has(m));
|
|
1328
|
+
} else
|
|
1329
|
+
return !a.reachedModulesFull.has(ap.moduleInfo);
|
|
1330
|
+
}
|
|
1331
|
+
__name(isLazyAPActive, "isLazyAPActive");
|
|
1332
|
+
function assertLazyAPActive(ap, a) {
|
|
1333
|
+
if (ap.dependents) {
|
|
1334
|
+
if (ap.moduleInfo.directDependents.values().every((m) => a.reachedModulesFull.has(m)))
|
|
1335
|
+
node_assert_1.default.fail(`Lazy access path ${ap} is irrelevant, all dependents are already reached`);
|
|
1336
|
+
} else if (a.reachedModulesFull.has(ap.moduleInfo))
|
|
1337
|
+
node_assert_1.default.fail(`Lazy access path ${ap} is irrelevant, module ${ap.moduleInfo} is already reached`);
|
|
1338
|
+
}
|
|
1339
|
+
__name(assertLazyAPActive, "assertLazyAPActive");
|
|
1340
|
+
function getExportedFunctionsByModule(ms, solver) {
|
|
1341
|
+
const roots = /* @__PURE__ */ new Set();
|
|
1342
|
+
for (const m of ms)
|
|
1343
|
+
(0, util_1.addAll)((0, escaping_1.findExportedTokens)(m, solver), roots);
|
|
1344
|
+
const [graph, anyFunction] = constructTokenReachabilityGraph(roots, solver);
|
|
1345
|
+
if (logger_1.default.isVerboseEnabled())
|
|
1346
|
+
logger_1.default.verbose(`Lazy: Exported tokens: ${graph.size}`);
|
|
1347
|
+
if (ms.size === 0 || !anyFunction)
|
|
1348
|
+
return /* @__PURE__ */ new Map();
|
|
1349
|
+
else if (ms.size === 1)
|
|
1350
|
+
return /* @__PURE__ */ new Map([[
|
|
1351
|
+
ms.values().next().value,
|
|
1352
|
+
graph.keys().filter((t) => t instanceof tokens_1.FunctionToken).toArray()
|
|
1353
|
+
]]);
|
|
1354
|
+
const [sccs, reps] = (0, scc_1.nuutila)(graph.keys(), (t) => graph.get(t));
|
|
1355
|
+
const sets = /* @__PURE__ */ new Map();
|
|
1356
|
+
for (const [t, rep] of reps.entries())
|
|
1357
|
+
(0, util_1.mapArrayAdd)(rep, t, sets);
|
|
1358
|
+
const modules = [...ms];
|
|
1359
|
+
const bitsets = new Map(sccs.map((t) => [t, bitset_1.BitSet.make(ms.size)]));
|
|
1360
|
+
for (const [i, m] of modules.entries())
|
|
1361
|
+
for (const t of (0, escaping_1.findExportedTokens)(m, solver))
|
|
1362
|
+
bitsets.get(reps.get(t)).set(i);
|
|
1363
|
+
const exportedFunctionsByModule = /* @__PURE__ */ new Map();
|
|
1364
|
+
for (const rep of sccs.reverse()) {
|
|
1365
|
+
const bs = bitsets.get(rep);
|
|
1366
|
+
(0, node_assert_1.default)(!bs.isEmpty());
|
|
1367
|
+
for (const t of sets.get(rep)) {
|
|
1368
|
+
const es = graph.get(t);
|
|
1369
|
+
if (es?.size)
|
|
1370
|
+
for (const t2 of es) {
|
|
1371
|
+
const rep2 = reps.get(t2);
|
|
1372
|
+
if (rep !== rep2)
|
|
1373
|
+
bitsets.get(rep2).unionUpdate(bs);
|
|
1374
|
+
}
|
|
1375
|
+
if (t instanceof tokens_1.FunctionToken)
|
|
1376
|
+
for (const i of bs)
|
|
1377
|
+
(0, util_1.mapArrayAdd)(modules[i], t, exportedFunctionsByModule);
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
return exportedFunctionsByModule;
|
|
1381
|
+
}
|
|
1382
|
+
__name(getExportedFunctionsByModule, "getExportedFunctionsByModule");
|
|
1383
|
+
}
|
|
1384
|
+
});
|
|
1385
|
+
|
|
1046
1386
|
// lib/analysis/solver.js
|
|
1047
1387
|
var require_solver = __commonJS({
|
|
1048
1388
|
"lib/analysis/solver.js"(exports) {
|
|
@@ -1106,6 +1446,7 @@ var require_solver = __commonJS({
|
|
|
1106
1446
|
var memory_1 = require_memory();
|
|
1107
1447
|
var diagnostics_1 = __importDefault(require_diagnostics());
|
|
1108
1448
|
var ecmascript_1 = require_ecmascript();
|
|
1449
|
+
var lazy_1 = require_lazy();
|
|
1109
1450
|
var CYCLE_ELIMINATION_MINIMUM = 100;
|
|
1110
1451
|
var CYCLE_ELIMINATION_FACTOR = 1.2;
|
|
1111
1452
|
var AbortedException = class extends Error {
|
|
@@ -1131,6 +1472,7 @@ var require_solver = __commonJS({
|
|
|
1131
1472
|
postponedListenersProcessed = 0;
|
|
1132
1473
|
phase;
|
|
1133
1474
|
timer = new timer_1.default();
|
|
1475
|
+
lazyRoundsHook;
|
|
1134
1476
|
constructor(abort) {
|
|
1135
1477
|
this.abort = abort;
|
|
1136
1478
|
}
|
|
@@ -1190,6 +1532,8 @@ var require_solver = __commonJS({
|
|
|
1190
1532
|
}
|
|
1191
1533
|
}
|
|
1192
1534
|
tokenAdded(toRep, t, ws) {
|
|
1535
|
+
if (options_1.options.lazyCleanup && t instanceof tokens_1.AccessPathToken && t.ap instanceof accesspaths_1.LazyAccessPath && !(0, lazy_1.isLazyAPActive)(t.ap, this.globalState))
|
|
1536
|
+
return ws;
|
|
1193
1537
|
if (logger_1.default.isDebugEnabled())
|
|
1194
1538
|
logger_1.default.debug(`Added token ${t} to ${toRep}`);
|
|
1195
1539
|
if (logger_1.default.isVerboseEnabled()) {
|
|
@@ -1208,14 +1552,14 @@ var require_solver = __commonJS({
|
|
|
1208
1552
|
if (!to)
|
|
1209
1553
|
return;
|
|
1210
1554
|
const abstractProp = ap instanceof accesspaths_1.PropertyAccessPath && !(subap instanceof accesspaths_1.ModuleAccessPath && ap.prop === "default") && options_1.patternProperties && !options_1.patternProperties.has(ap.prop);
|
|
1211
|
-
const ap2 = this.globalState.canonicalizeAccessPath(subap instanceof accesspaths_1.IgnoredAccessPath || subap instanceof accesspaths_1.UnknownAccessPath && (ap instanceof accesspaths_1.CallResultAccessPath || ap instanceof accesspaths_1.ComponentAccessPath || abstractProp) ? subap : abstractProp ? new accesspaths_1.PropertyAccessPath(ap.base, "?") : ap);
|
|
1555
|
+
const ap2 = this.globalState.canonicalizeAccessPath(subap instanceof accesspaths_1.IgnoredAccessPath || subap instanceof accesspaths_1.LazyAccessPath || subap instanceof accesspaths_1.UnknownAccessPath && (ap instanceof accesspaths_1.CallResultAccessPath || ap instanceof accesspaths_1.ComponentAccessPath || abstractProp) ? subap : abstractProp ? new accesspaths_1.PropertyAccessPath(ap.base, "?") : ap);
|
|
1212
1556
|
if (logger_1.default.isDebugEnabled())
|
|
1213
1557
|
logger_1.default.debug(`Adding access path ${ap2}${ap2 !== ap ? ` (${ap})` : ""} at ${to}${subap ? ` (sub-expression access path: ${subap})` : ""}`);
|
|
1214
1558
|
const f = this.fragmentState;
|
|
1215
1559
|
const asn = to instanceof constraintvars_1.NodeVar && (0, types_1.isAssignmentExpression)(to.node);
|
|
1216
1560
|
if (!asn)
|
|
1217
1561
|
this.addToken(f.a.canonicalizeToken(new tokens_1.AccessPathToken(ap2)), f.getRepresentative(to));
|
|
1218
|
-
if (!(ap2 instanceof accesspaths_1.UnknownAccessPath || ap2 instanceof accesspaths_1.IgnoredAccessPath) && (to instanceof constraintvars_1.NodeVar || to instanceof constraintvars_1.IntermediateVar && to.label === "import")) {
|
|
1562
|
+
if (!(ap2 instanceof accesspaths_1.UnknownAccessPath || ap2 instanceof accesspaths_1.IgnoredAccessPath || ap2 instanceof accesspaths_1.LazyAccessPath) && (to instanceof constraintvars_1.NodeVar || to instanceof constraintvars_1.IntermediateVar && to.label === "import")) {
|
|
1219
1563
|
(0, assert_1.default)(node !== void 0 && encl !== void 0);
|
|
1220
1564
|
if (ap2 instanceof accesspaths_1.ModuleAccessPath)
|
|
1221
1565
|
(0, util_1.mapGetMap)(f.moduleAccessPaths, ap2).set(node, encl);
|
|
@@ -1793,18 +2137,46 @@ var require_modulefinder = __commonJS({
|
|
|
1793
2137
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1794
2138
|
exports.findModules = findModules;
|
|
1795
2139
|
var types_1 = __require("@babel/types");
|
|
2140
|
+
var util_1 = require_util();
|
|
1796
2141
|
var traverse_1 = __importDefault(__require("@babel/traverse"));
|
|
1797
2142
|
var module_1 = __importDefault(__require("module"));
|
|
2143
|
+
var infos_1 = require_infos();
|
|
2144
|
+
var micromatch_1 = __importDefault(require_micromatch());
|
|
2145
|
+
var options_1 = require_options();
|
|
2146
|
+
var logger_1 = __importDefault(require_logger());
|
|
2147
|
+
var asthelpers_1 = require_asthelpers();
|
|
1798
2148
|
function findModules(ast, f, moduleInfo) {
|
|
1799
2149
|
function loadModule(mode, str, path) {
|
|
1800
|
-
if (!module_1.default.isBuiltin(str))
|
|
1801
|
-
f.loadModule(mode, str, path, moduleInfo);
|
|
2150
|
+
if (!module_1.default.isBuiltin(str)) {
|
|
2151
|
+
const m = f.loadModule(mode, str, path, moduleInfo);
|
|
2152
|
+
if (m && options_1.options.lazy) {
|
|
2153
|
+
const s = (0, infos_1.normalizeModuleName)(str);
|
|
2154
|
+
const tracked = options_1.options.trackedModules?.some((e) => micromatch_1.default.isMatch(m.getOfficialName(), e) || micromatch_1.default.isMatch(s, e));
|
|
2155
|
+
if (tracked) {
|
|
2156
|
+
if (logger_1.default.isVerboseEnabled())
|
|
2157
|
+
logger_1.default.verbose(`Lazy: Module ${moduleInfo} imports tracked module ${m}`);
|
|
2158
|
+
f.a.reachedModuleFull(moduleInfo);
|
|
2159
|
+
}
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
1802
2162
|
}
|
|
1803
2163
|
__name(loadModule, "loadModule");
|
|
2164
|
+
function isRequire(path) {
|
|
2165
|
+
if (!path.isExpression() || path.scope.getBinding("require"))
|
|
2166
|
+
return false;
|
|
2167
|
+
const aux = /* @__PURE__ */ __name((path2) => {
|
|
2168
|
+
path2 = (0, asthelpers_1.skipParenthesizedChildren)(path2);
|
|
2169
|
+
if (path2.isIdentifier({ name: "require" }))
|
|
2170
|
+
return true;
|
|
2171
|
+
return path2.isConditionalExpression() && (aux(path2.get("consequent")) || aux(path2.get("alternate")));
|
|
2172
|
+
}, "aux");
|
|
2173
|
+
return aux(path);
|
|
2174
|
+
}
|
|
2175
|
+
__name(isRequire, "isRequire");
|
|
1804
2176
|
(0, traverse_1.default)(ast, {
|
|
1805
2177
|
CallExpression(path) {
|
|
1806
2178
|
const imp = (0, types_1.isImport)(path.node.callee);
|
|
1807
|
-
if ((imp || (
|
|
2179
|
+
if ((imp || isRequire(path.get("callee"))) && path.node.arguments.length >= 1) {
|
|
1808
2180
|
const arg = path.node.arguments[0];
|
|
1809
2181
|
if ((0, types_1.isStringLiteral)(arg))
|
|
1810
2182
|
loadModule(imp ? "module" : "commonjs", arg.value, path);
|
|
@@ -1821,104 +2193,35 @@ var require_modulefinder = __commonJS({
|
|
|
1821
2193
|
ExportNamedDeclaration(path) {
|
|
1822
2194
|
if (path.node.source)
|
|
1823
2195
|
loadModule("module", path.node.source.value, path);
|
|
1824
|
-
}
|
|
2196
|
+
},
|
|
2197
|
+
...options_1.options.lazy ? {
|
|
2198
|
+
Identifier(path) {
|
|
2199
|
+
const { node, parent } = path;
|
|
2200
|
+
if (!isRequire(path) || (0, types_1.isCallExpression)(parent, { callee: node }) || ((0, types_1.isMemberExpression)(parent, { object: node }) || (0, types_1.isOptionalMemberExpression)(parent, { object: node })) && ["main", "cache", "resolve", "extensions"].includes((0, asthelpers_1.getProperty)(parent)) || (0, types_1.isUnaryExpression)(parent, { argument: node }))
|
|
2201
|
+
return;
|
|
2202
|
+
let p = path;
|
|
2203
|
+
while (true) {
|
|
2204
|
+
const pp = p.parentPath;
|
|
2205
|
+
if (!pp)
|
|
2206
|
+
return;
|
|
2207
|
+
if (pp.isParenthesizedExpression() || pp.isConditionalExpression({ consequent: p.node }) || pp.isConditionalExpression({ alternate: p.node }))
|
|
2208
|
+
p = pp;
|
|
2209
|
+
else if (pp.isCallExpression({ callee: p.node }) && pp.node.arguments.length >= 1)
|
|
2210
|
+
return;
|
|
2211
|
+
else
|
|
2212
|
+
break;
|
|
2213
|
+
}
|
|
2214
|
+
if (logger_1.default.isVerboseEnabled())
|
|
2215
|
+
logger_1.default.verbose(`Lazy: Aliasing 'require' at ${(0, util_1.locationToStringWithFileAndEnd)(path.node.loc)} in ${moduleInfo}`);
|
|
2216
|
+
f.a.reachedModuleFull(moduleInfo);
|
|
2217
|
+
}
|
|
2218
|
+
} : {}
|
|
1825
2219
|
});
|
|
1826
2220
|
}
|
|
1827
2221
|
__name(findModules, "findModules");
|
|
1828
2222
|
}
|
|
1829
2223
|
});
|
|
1830
2224
|
|
|
1831
|
-
// lib/analysis/escaping.js
|
|
1832
|
-
var require_escaping = __commonJS({
|
|
1833
|
-
"lib/analysis/escaping.js"(exports) {
|
|
1834
|
-
"use strict";
|
|
1835
|
-
var __importDefault = exports && exports.__importDefault || function(mod) {
|
|
1836
|
-
return mod && mod.__esModule ? mod : { "default": mod };
|
|
1837
|
-
};
|
|
1838
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1839
|
-
exports.findEscapingObjects = findEscapingObjects;
|
|
1840
|
-
var tokens_1 = require_tokens();
|
|
1841
|
-
var logger_1 = __importDefault(require_logger());
|
|
1842
|
-
var types_1 = __require("@babel/types");
|
|
1843
|
-
var accesspaths_1 = require_accesspaths();
|
|
1844
|
-
var ecmascript_1 = require_ecmascript();
|
|
1845
|
-
var options_1 = require_options();
|
|
1846
|
-
var packagejson_1 = require_packagejson();
|
|
1847
|
-
function findEscapingObjects(ms, solver) {
|
|
1848
|
-
const a = solver.globalState;
|
|
1849
|
-
const f = solver.fragmentState;
|
|
1850
|
-
const worklist = [];
|
|
1851
|
-
const visited = /* @__PURE__ */ new Set();
|
|
1852
|
-
const escaping = /* @__PURE__ */ new Set();
|
|
1853
|
-
const theUnknownAccessPathToken = a.canonicalizeToken(new tokens_1.AccessPathToken(accesspaths_1.UnknownAccessPath.instance));
|
|
1854
|
-
function addToWorklist(v) {
|
|
1855
|
-
for (const t of v instanceof tokens_1.Token ? [v] : f.getTokens(f.getRepresentative(v)))
|
|
1856
|
-
if ((t instanceof tokens_1.AllocationSiteToken || t instanceof tokens_1.FunctionToken || t instanceof tokens_1.NativeObjectToken && t.name === "exports") && !visited.has(t)) {
|
|
1857
|
-
worklist.push(t);
|
|
1858
|
-
visited.add(t);
|
|
1859
|
-
}
|
|
1860
|
-
}
|
|
1861
|
-
__name(addToWorklist, "addToWorklist");
|
|
1862
|
-
for (const m of Array.isArray(ms) ? ms : [ms])
|
|
1863
|
-
if (m.packageInfo.isEntry && (m.getPath().includes("node_modules") || options_1.options.library)) {
|
|
1864
|
-
const pi = a.packageJsonInfos.get(m.packageInfo.dir);
|
|
1865
|
-
if (!pi?.exports || (0, packagejson_1.isInExports)(`./${m.relativePath}`, pi.exports))
|
|
1866
|
-
addToWorklist(f.varProducer.objPropVar(a.canonicalizeToken(new tokens_1.NativeObjectToken("module", m)), "exports"));
|
|
1867
|
-
}
|
|
1868
|
-
const w2 = [];
|
|
1869
|
-
while (worklist.length !== 0) {
|
|
1870
|
-
const t = worklist.pop();
|
|
1871
|
-
if (t instanceof tokens_1.FunctionToken)
|
|
1872
|
-
w2.push(t);
|
|
1873
|
-
else if (t instanceof tokens_1.ObjectToken || t instanceof tokens_1.NativeObjectToken && t.name === "exports") {
|
|
1874
|
-
for (const p of f.objectProperties.get(t) ?? [])
|
|
1875
|
-
if (!(0, ecmascript_1.isInternalProperty)(p))
|
|
1876
|
-
addToWorklist(f.varProducer.objPropVar(t, p));
|
|
1877
|
-
}
|
|
1878
|
-
}
|
|
1879
|
-
visited.clear();
|
|
1880
|
-
for (const t of w2) {
|
|
1881
|
-
visited.add(t);
|
|
1882
|
-
worklist.push(t);
|
|
1883
|
-
}
|
|
1884
|
-
for (const v of f.maybeEscaping)
|
|
1885
|
-
addToWorklist(v);
|
|
1886
|
-
f.maybeEscaping.clear();
|
|
1887
|
-
while (worklist.length !== 0) {
|
|
1888
|
-
const t = worklist.pop();
|
|
1889
|
-
if (t instanceof tokens_1.ObjectToken) {
|
|
1890
|
-
if (logger_1.default.isDebugEnabled())
|
|
1891
|
-
logger_1.default.debug(`Escaping object: ${t}`);
|
|
1892
|
-
escaping.add(t);
|
|
1893
|
-
}
|
|
1894
|
-
if (t instanceof tokens_1.FunctionToken) {
|
|
1895
|
-
addToWorklist(f.varProducer.returnVar(t.fun));
|
|
1896
|
-
for (const param of t.fun.params)
|
|
1897
|
-
if ((0, types_1.isIdentifier)(param))
|
|
1898
|
-
solver.addToken(theUnknownAccessPathToken, f.getRepresentative(f.varProducer.nodeVar(param)));
|
|
1899
|
-
solver.addToken(theUnknownAccessPathToken, f.getRepresentative(f.varProducer.thisVar(t.fun)));
|
|
1900
|
-
}
|
|
1901
|
-
for (const p of f.objectProperties.get(t) ?? [])
|
|
1902
|
-
if (!(0, ecmascript_1.isInternalProperty)(p)) {
|
|
1903
|
-
const w = f.varProducer.objPropVar(t, p);
|
|
1904
|
-
addToWorklist(w);
|
|
1905
|
-
solver.addToken(theUnknownAccessPathToken, f.getRepresentative(w));
|
|
1906
|
-
}
|
|
1907
|
-
}
|
|
1908
|
-
if (logger_1.default.isVerboseEnabled()) {
|
|
1909
|
-
const objecttokens = /* @__PURE__ */ new Set();
|
|
1910
|
-
for (const [, ts] of f.getAllVarsAndTokens())
|
|
1911
|
-
for (const t of ts)
|
|
1912
|
-
if (t instanceof tokens_1.ObjectToken)
|
|
1913
|
-
objecttokens.add(t);
|
|
1914
|
-
logger_1.default.verbose(`Escaping objects: ${escaping.size}/${objecttokens.size}`);
|
|
1915
|
-
}
|
|
1916
|
-
return escaping;
|
|
1917
|
-
}
|
|
1918
|
-
__name(findEscapingObjects, "findEscapingObjects");
|
|
1919
|
-
}
|
|
1920
|
-
});
|
|
1921
|
-
|
|
1922
2225
|
// lib/natives/nativebuilder.js
|
|
1923
2226
|
var require_nativebuilder = __commonJS({
|
|
1924
2227
|
"lib/natives/nativebuilder.js"(exports) {
|
|
@@ -2833,6 +3136,14 @@ var require_operations = __commonJS({
|
|
|
2833
3136
|
} else if ((0, types_1.isSpreadElement)(args[i]))
|
|
2834
3137
|
f.warnUnsupported(args[i], "SpreadElement in arguments to external function");
|
|
2835
3138
|
}
|
|
3139
|
+
if (t.ap instanceof accesspaths_1.LazyAccessPath) {
|
|
3140
|
+
const s = (0, util_1.mapGetSet)(this.solver.fragmentState.lazyEscaping, t.ap);
|
|
3141
|
+
for (let i = 0; i < argVars.length; i++) {
|
|
3142
|
+
const argVar = argVars[i];
|
|
3143
|
+
if (argVar)
|
|
3144
|
+
s.add(argVar);
|
|
3145
|
+
}
|
|
3146
|
+
}
|
|
2836
3147
|
}
|
|
2837
3148
|
if (isNew && t instanceof tokens_1.FunctionToken) {
|
|
2838
3149
|
const q = this.newObjectToken(t.fun);
|
|
@@ -3036,6 +3347,8 @@ var require_operations = __commonJS({
|
|
|
3036
3347
|
} else if (lVar && base instanceof tokens_1.AccessPathToken) {
|
|
3037
3348
|
this.solver.addAccessPath(new accesspaths_1.PropertyAccessPath(lVar, prop), this.solver.varProducer.nodeVar(escapeNode), escapeNode, enclosing, base.ap);
|
|
3038
3349
|
this.solver.fragmentState.registerEscapingToExternal(src, escapeNode, enclosing);
|
|
3350
|
+
if (src && base.ap instanceof accesspaths_1.LazyAccessPath)
|
|
3351
|
+
(0, util_1.mapGetSet)(this.solver.fragmentState.lazyEscaping, base.ap).add(src);
|
|
3039
3352
|
}
|
|
3040
3353
|
}
|
|
3041
3354
|
loadModule(mode, str, resultVar, path) {
|
|
@@ -3049,18 +3362,24 @@ var require_operations = __commonJS({
|
|
|
3049
3362
|
f.warnUnsupported(path.node, `Ignoring re-export from built-in module '${str}'`);
|
|
3050
3363
|
} else {
|
|
3051
3364
|
m = f.loadModule(mode, str, path, this.moduleInfo);
|
|
3052
|
-
if (m instanceof infos_1.ModuleInfo && m.isIncluded) {
|
|
3053
|
-
const fp = (0, asthelpers_1.getEnclosingFunction)(path)?.node;
|
|
3054
|
-
const from = fp ? this.a.functionInfos.get(fp) : this.moduleInfo;
|
|
3055
|
-
f.registerRequireEdge(from, m);
|
|
3056
|
-
if (!reexport)
|
|
3057
|
-
this.solver.addSubsetConstraint(this.solver.varProducer.objPropVar(this.a.canonicalizeToken(new tokens_1.NativeObjectToken("module", m)), "exports"), resultVar);
|
|
3058
|
-
}
|
|
3059
3365
|
if (m) {
|
|
3366
|
+
if (m instanceof infos_1.ModuleInfo && m.isIncluded) {
|
|
3367
|
+
const fp = (0, asthelpers_1.getEnclosingFunction)(path)?.node;
|
|
3368
|
+
const from = fp ? this.a.functionInfos.get(fp) : this.moduleInfo;
|
|
3369
|
+
f.registerRequireEdge(from, m);
|
|
3370
|
+
if (!reexport)
|
|
3371
|
+
this.solver.addSubsetConstraint(this.solver.varProducer.objPropVar(this.a.canonicalizeToken(new tokens_1.NativeObjectToken("module", m)), "exports"), resultVar);
|
|
3372
|
+
if (options_1.options.lazy && !this.a.reachedModulesFull.has(m) && resultVar) {
|
|
3373
|
+
const ap = new accesspaths_1.LazyAccessPath(m, false);
|
|
3374
|
+
if (logger_1.default.isVerboseEnabled())
|
|
3375
|
+
logger_1.default.verbose(`Lazy: Injecting ${ap} at ${resultVar}`);
|
|
3376
|
+
this.solver.addAccessPath(ap, resultVar);
|
|
3377
|
+
}
|
|
3378
|
+
}
|
|
3060
3379
|
const analyzed = m instanceof infos_1.ModuleInfo && m.isIncluded;
|
|
3061
3380
|
if (!analyzed || options_1.options.vulnerabilities || options_1.options.vulnerabilitiesJson) {
|
|
3062
3381
|
const s = (0, infos_1.normalizeModuleName)(str);
|
|
3063
|
-
const tracked = options_1.options.trackedModules && options_1.options.trackedModules.
|
|
3382
|
+
const tracked = options_1.options.trackedModules && options_1.options.trackedModules.some((e) => micromatch_1.default.isMatch(m.getOfficialName(), e) || micromatch_1.default.isMatch(s, e));
|
|
3064
3383
|
const ap = tracked ? new accesspaths_1.ModuleAccessPath(m, s) : accesspaths_1.IgnoredAccessPath.instance;
|
|
3065
3384
|
this.solver.addAccessPath(ap, resultVar, path.node, this.a.getEnclosingFunctionOrModule(path));
|
|
3066
3385
|
if ((0, types_1.isExportAllDeclaration)(path.node))
|
|
@@ -3517,7 +3836,7 @@ var require_finalization = __commonJS({
|
|
|
3517
3836
|
}
|
|
3518
3837
|
}
|
|
3519
3838
|
}
|
|
3520
|
-
solver.diagnostics.finalizationTime
|
|
3839
|
+
solver.diagnostics.finalizationTime += finalTimer.elapsed();
|
|
3521
3840
|
}
|
|
3522
3841
|
__name(finalizeCallEdges, "finalizeCallEdges");
|
|
3523
3842
|
}
|
|
@@ -3863,6 +4182,9 @@ var require_analyzer = __commonJS({
|
|
|
3863
4182
|
return result;
|
|
3864
4183
|
};
|
|
3865
4184
|
})();
|
|
4185
|
+
var __importDefault = exports && exports.__importDefault || function(mod) {
|
|
4186
|
+
return mod && mod.__esModule ? mod : { "default": mod };
|
|
4187
|
+
};
|
|
3866
4188
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3867
4189
|
exports.analyzeFiles = analyzeFiles;
|
|
3868
4190
|
var fs_1 = __importStar(__require("fs"));
|
|
@@ -3877,6 +4199,7 @@ var require_analyzer = __commonJS({
|
|
|
3877
4199
|
var modulefinder_1 = require_modulefinder();
|
|
3878
4200
|
var parser_1 = require_parser();
|
|
3879
4201
|
var escaping_1 = require_escaping();
|
|
4202
|
+
var lazy_1 = require_lazy();
|
|
3880
4203
|
var nativebuilder_1 = require_nativebuilder();
|
|
3881
4204
|
var analysisstatereporter_1 = require_analysisstatereporter();
|
|
3882
4205
|
var operations_1 = require_operations();
|
|
@@ -3888,6 +4211,10 @@ var require_analyzer = __commonJS({
|
|
|
3888
4211
|
var patching_1 = require_patching();
|
|
3889
4212
|
var diagnostics_1 = require_diagnostics2();
|
|
3890
4213
|
var patchthis_1 = require_patchthis();
|
|
4214
|
+
var assert_1 = __importDefault(__require("assert"));
|
|
4215
|
+
var accesspaths_1 = require_accesspaths();
|
|
4216
|
+
var tokens_1 = require_tokens();
|
|
4217
|
+
var types_1 = __require("@babel/types");
|
|
3891
4218
|
async function analyzeFiles(files, solver) {
|
|
3892
4219
|
const a = solver.globalState;
|
|
3893
4220
|
const d = solver.diagnostics;
|
|
@@ -3912,49 +4239,63 @@ var require_analyzer = __commonJS({
|
|
|
3912
4239
|
logger_1.default.info(`Loading ${options_1.options.approxLoad}`);
|
|
3913
4240
|
a.approx.add(JSON.parse((0, fs_1.readFileSync)(options_1.options.approxLoad, "utf-8")));
|
|
3914
4241
|
}
|
|
3915
|
-
while (a.pendingFiles.isNonEmpty()) {
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
d.
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
4242
|
+
while (a.pendingFiles.isNonEmpty() || a.pendingModulesFull.isNonEmpty()) {
|
|
4243
|
+
d.analyzerRounds++;
|
|
4244
|
+
const prevModulesFull = d.modulesFull;
|
|
4245
|
+
while (a.pendingFiles.isNonEmpty() || a.pendingModulesFull.isNonEmpty()) {
|
|
4246
|
+
while (a.pendingFiles.isNonEmpty() || a.pendingModulesFull.isNonEmpty()) {
|
|
4247
|
+
for (const file of a.pendingFiles) {
|
|
4248
|
+
const moduleInfo = a.getModuleInfo(file);
|
|
4249
|
+
d.packages = a.packageInfos.size;
|
|
4250
|
+
if (!options_1.options.modulesOnly && options_1.options.printProgress)
|
|
4251
|
+
logger_1.default.info(`Loading ${moduleInfo} (${d.modules})`);
|
|
4252
|
+
const str = fs_1.default.readFileSync(file, "utf8");
|
|
4253
|
+
(0, logger_1.writeStdOutIfActive)(`Parsing ${file} (${Math.ceil(str.length / 1024)}KB)...`);
|
|
4254
|
+
const ast = (0, parser_1.parseAndDesugar)(str, file, solver.fragmentState);
|
|
4255
|
+
if (!ast) {
|
|
4256
|
+
a.filesWithParseErrors.push(file);
|
|
4257
|
+
continue;
|
|
4258
|
+
}
|
|
4259
|
+
moduleInfo.loc = ast.program.loc;
|
|
4260
|
+
moduleInfo.ast = ast;
|
|
4261
|
+
a.modules.set(moduleInfo, ast.program);
|
|
4262
|
+
a.filesAnalyzed.push(file);
|
|
4263
|
+
const fileSize = (0, fs_1.statSync)(file).size;
|
|
4264
|
+
d.modules++;
|
|
4265
|
+
d.codeSize += fileSize;
|
|
4266
|
+
if (moduleInfo.packageInfo.isEntry)
|
|
4267
|
+
d.codeSizeMain += fileSize;
|
|
4268
|
+
else
|
|
4269
|
+
d.codeSizeDependencies += fileSize;
|
|
4270
|
+
if (options_1.options.approx) {
|
|
4271
|
+
if (a.approx.hints.moduleIndex.has(moduleInfo.toString())) {
|
|
4272
|
+
if (logger_1.default.isVerboseEnabled())
|
|
4273
|
+
logger_1.default.verbose(`Skipping approximate interpretation of module ${file}, already visited`);
|
|
4274
|
+
} else {
|
|
4275
|
+
(0, logger_1.writeStdOutIfActive)(`Approximate interpretation...`);
|
|
4276
|
+
await a.approx.execute(file);
|
|
4277
|
+
}
|
|
4278
|
+
}
|
|
4279
|
+
if (options_1.options.modulesOnly || options_1.options.lazy) {
|
|
4280
|
+
(0, modulefinder_1.findModules)(ast, solver.fragmentState, moduleInfo);
|
|
3943
4281
|
} else {
|
|
3944
|
-
|
|
3945
|
-
await a.approx.execute(file);
|
|
4282
|
+
a.reachedModuleFull(moduleInfo);
|
|
3946
4283
|
}
|
|
3947
|
-
}
|
|
3948
|
-
if (options_1.options.modulesOnly) {
|
|
3949
|
-
(0, modulefinder_1.findModules)(ast, solver.fragmentState, moduleInfo);
|
|
3950
4284
|
if (d.modules % 16 === 0)
|
|
3951
4285
|
a.timeoutTimer.checkTimeout();
|
|
3952
|
-
}
|
|
4286
|
+
}
|
|
4287
|
+
for (const moduleInfo of a.pendingModulesFull) {
|
|
4288
|
+
const ast = moduleInfo.ast;
|
|
4289
|
+
(0, assert_1.default)(ast);
|
|
4290
|
+
d.modulesFull++;
|
|
4291
|
+
if (!options_1.options.modulesOnly && options_1.options.printProgress)
|
|
4292
|
+
logger_1.default.info(`Analyzing ${moduleInfo}`);
|
|
3953
4293
|
const moduleParams = (0, extras_1.preprocessAst)(ast, moduleInfo);
|
|
3954
4294
|
(0, logger_1.writeStdOutIfActive)("Traversing AST...");
|
|
3955
4295
|
(0, astvisitor_1.visit)(ast, new operations_1.Operations(moduleInfo, solver, (0, nativebuilder_1.buildModuleNatives)(solver, moduleInfo, moduleParams)));
|
|
4296
|
+
ast.tokens = void 0;
|
|
4297
|
+
moduleInfo.ast = void 0;
|
|
3956
4298
|
}
|
|
3957
|
-
ast.tokens = void 0;
|
|
3958
4299
|
}
|
|
3959
4300
|
await solver.propagate("Analyzing");
|
|
3960
4301
|
solver.updateDiagnostics();
|
|
@@ -3985,6 +4326,107 @@ var require_analyzer = __commonJS({
|
|
|
3985
4326
|
}
|
|
3986
4327
|
solver.updateDiagnostics();
|
|
3987
4328
|
}
|
|
4329
|
+
if (options_1.options.lazy && d.modulesFull > prevModulesFull) {
|
|
4330
|
+
const f2 = solver.fragmentState;
|
|
4331
|
+
(0, logger_1.writeStdOutIfActive)("Lazy module analysis...");
|
|
4332
|
+
solver.lazyRoundsHook?.();
|
|
4333
|
+
const funs = /* @__PURE__ */ new Map();
|
|
4334
|
+
for (const [vs, fun] of a.vulnerabilities.patternMatch(solver.fragmentState, void 0, solver.diagnostics).values())
|
|
4335
|
+
(0, util_1.addAll)(vs, (0, util_1.mapGetSet)(funs, fun));
|
|
4336
|
+
const reachingFunctions = /* @__PURE__ */ new Set();
|
|
4337
|
+
if (funs.size) {
|
|
4338
|
+
(0, finalization_1.finalizeCallEdges)(solver);
|
|
4339
|
+
(0, util_1.addAll)(a.vulnerabilities.findFunctionsThatMayReachVulnerableFunctions(funs, f2).keys(), reachingFunctions);
|
|
4340
|
+
}
|
|
4341
|
+
if (logger_1.default.isVerboseEnabled())
|
|
4342
|
+
logger_1.default.verbose(`Lazy: Functions that may reach vulnerable functions: ${reachingFunctions.size}`);
|
|
4343
|
+
const isCandidate = /* @__PURE__ */ __name((m) => m.directDependents.values().some((d2) => !a.reachedModulesFull.has(d2)), "isCandidate");
|
|
4344
|
+
const candidateModules = new Set(a.reachedModulesFull.values().filter(isCandidate));
|
|
4345
|
+
if (logger_1.default.isVerboseEnabled())
|
|
4346
|
+
logger_1.default.verbose(`Lazy: Candidate modules: ${candidateModules.size}`);
|
|
4347
|
+
let reevaluateCandidates = false;
|
|
4348
|
+
for (const r of reachingFunctions)
|
|
4349
|
+
if (r instanceof infos_1.ModuleInfo && candidateModules.has(r)) {
|
|
4350
|
+
logger_1.default.verbose(`Lazy: top-level function ${r} may reach vulnerable function`);
|
|
4351
|
+
for (const d2 of r.directDependents)
|
|
4352
|
+
a.reachedModuleFull(d2);
|
|
4353
|
+
candidateModules.delete(r);
|
|
4354
|
+
reevaluateCandidates = true;
|
|
4355
|
+
}
|
|
4356
|
+
if (reevaluateCandidates) {
|
|
4357
|
+
for (const m of candidateModules)
|
|
4358
|
+
if (!isCandidate(m)) {
|
|
4359
|
+
logger_1.default.verbose(`Lazy: Candidate module ${m}'s non-analyzed dependents were all reached`);
|
|
4360
|
+
candidateModules.delete(m);
|
|
4361
|
+
}
|
|
4362
|
+
}
|
|
4363
|
+
for (const [m, ts] of (0, lazy_1.getExportedFunctionsByModule)(candidateModules, solver)) {
|
|
4364
|
+
const ap = new accesspaths_1.LazyAccessPath(m, true);
|
|
4365
|
+
for (const t of ts) {
|
|
4366
|
+
for (const param of t.fun.params)
|
|
4367
|
+
if ((0, types_1.isIdentifier)(param))
|
|
4368
|
+
solver.addAccessPath(ap, f2.varProducer.nodeVar(param));
|
|
4369
|
+
if (f2.functionsWithThis.has(t.fun))
|
|
4370
|
+
solver.addAccessPath(ap, f2.varProducer.thisVar(t.fun));
|
|
4371
|
+
if (f2.functionsWithArguments.has(t.fun))
|
|
4372
|
+
solver.addAccessPath(ap, f2.varProducer.argumentsVar(t.fun));
|
|
4373
|
+
}
|
|
4374
|
+
}
|
|
4375
|
+
await solver.propagate("Lazy loading");
|
|
4376
|
+
for (const m of candidateModules) {
|
|
4377
|
+
const ap = a.canonicalizeAccessPath(new accesspaths_1.LazyAccessPath(m, true));
|
|
4378
|
+
(0, lazy_1.assertLazyAPActive)(ap, a);
|
|
4379
|
+
const v = f2.varProducer.objPropVar(a.canonicalizeToken(new tokens_1.NativeObjectToken("module", m)), "exports");
|
|
4380
|
+
(0, util_1.mapGetSet)(f2.lazyEscaping, ap).add(v);
|
|
4381
|
+
}
|
|
4382
|
+
const roots = /* @__PURE__ */ new Set();
|
|
4383
|
+
const lazyEscapingTokens = /* @__PURE__ */ new Map();
|
|
4384
|
+
for (const [ap, vs] of f2.lazyEscaping) {
|
|
4385
|
+
if (!(0, lazy_1.isLazyAPActive)(ap, a)) {
|
|
4386
|
+
f2.lazyEscaping.delete(ap);
|
|
4387
|
+
continue;
|
|
4388
|
+
}
|
|
4389
|
+
const ts = /* @__PURE__ */ new Set();
|
|
4390
|
+
for (const v of vs)
|
|
4391
|
+
(0, util_1.addAll)(f2.getTokens(f2.getRepresentative(v)), ts);
|
|
4392
|
+
(0, util_1.addAll)(ts, roots);
|
|
4393
|
+
lazyEscapingTokens.set(ap, ts);
|
|
4394
|
+
}
|
|
4395
|
+
const [graph] = (0, lazy_1.constructTokenReachabilityGraph)(roots, solver);
|
|
4396
|
+
const vulnTokens = graph.keys().filter((t) => t instanceof tokens_1.AccessPathToken && !(t.ap instanceof accesspaths_1.UnknownAccessPath || t.ap instanceof accesspaths_1.IgnoredAccessPath || t.ap instanceof accesspaths_1.LazyAccessPath) || t instanceof tokens_1.FunctionToken && reachingFunctions.has(a.functionInfos.get(t.fun))).toArray();
|
|
4397
|
+
if (vulnTokens.length) {
|
|
4398
|
+
const rGraph = (0, util_1.getReverseGraph)(graph);
|
|
4399
|
+
const worklist = vulnTokens;
|
|
4400
|
+
const visited = new Set(worklist);
|
|
4401
|
+
while (worklist.length) {
|
|
4402
|
+
const t = worklist.pop();
|
|
4403
|
+
const es = rGraph.get(t);
|
|
4404
|
+
if (es) {
|
|
4405
|
+
for (const t2 of es)
|
|
4406
|
+
if (!visited.has(t2)) {
|
|
4407
|
+
visited.add(t2);
|
|
4408
|
+
worklist.push(t2);
|
|
4409
|
+
}
|
|
4410
|
+
}
|
|
4411
|
+
}
|
|
4412
|
+
for (const [ap, ts] of lazyEscapingTokens)
|
|
4413
|
+
for (const t of ts)
|
|
4414
|
+
if (visited.has(t)) {
|
|
4415
|
+
if (ap.dependents) {
|
|
4416
|
+
if (logger_1.default.isVerboseEnabled())
|
|
4417
|
+
logger_1.default.verbose(`Lazy: Including ${ap.moduleInfo.directDependents.size} dependents of ${ap.moduleInfo}`);
|
|
4418
|
+
for (const d2 of ap.moduleInfo.directDependents)
|
|
4419
|
+
a.reachedModuleFull(d2);
|
|
4420
|
+
} else {
|
|
4421
|
+
if (logger_1.default.isVerboseEnabled())
|
|
4422
|
+
logger_1.default.verbose(`Lazy: Including ${ap.moduleInfo}`);
|
|
4423
|
+
a.reachedModuleFull(ap.moduleInfo);
|
|
4424
|
+
}
|
|
4425
|
+
break;
|
|
4426
|
+
}
|
|
4427
|
+
}
|
|
4428
|
+
solver.updateDiagnostics();
|
|
4429
|
+
}
|
|
3988
4430
|
}
|
|
3989
4431
|
}
|
|
3990
4432
|
const f = solver.fragmentState;
|
|
@@ -4030,7 +4472,7 @@ var require_analyzer = __commonJS({
|
|
|
4030
4472
|
d.functionsWithZeroCallers = r.getZeroCallerFunctions().size;
|
|
4031
4473
|
d.reachableFunctions = Array.from(r.getReachableModulesAndFunctions(r.getEntryModules())).filter((r2) => r2 instanceof infos_1.FunctionInfo).length;
|
|
4032
4474
|
if (logger_1.default.isInfoEnabled()) {
|
|
4033
|
-
logger_1.default.info(`Analyzed packages: ${d.packages}, modules: ${d.modules}, functions: ${a.functionInfos.size}, code size main: ${Math.ceil(d.codeSizeMain / 1024)}KB, dependencies: ${Math.ceil(d.codeSizeDependencies / 1024)}KB`);
|
|
4475
|
+
logger_1.default.info(`Analyzed packages: ${d.packages}, modules: ${d.modules} (full: ${d.modulesFull}), functions: ${a.functionInfos.size}, code size main: ${Math.ceil(d.codeSizeMain / 1024)}KB, dependencies: ${Math.ceil(d.codeSizeDependencies / 1024)}KB`);
|
|
4034
4476
|
logger_1.default.info(`Call edges function->function: ${d.functionToFunctionEdges}, call->function: ${d.callToFunctionEdges}`);
|
|
4035
4477
|
const total = d.totalCallSites, zeroOne = d.callsWithNoCallee + d.callsWithUniqueCallee, nativeExternal = d.nativeOnlyCalls + d.externalOnlyCalls + d.nativeOrExternalCalls;
|
|
4036
4478
|
if (total > 0)
|
|
@@ -8148,7 +8590,7 @@ var require_patternmatcher = __commonJS({
|
|
|
8148
8590
|
const f = this.fragmentState;
|
|
8149
8591
|
for (const [v, m] of f.maybeEscapingToExternal)
|
|
8150
8592
|
for (const t of f.getTokens(f.getRepresentative(v)))
|
|
8151
|
-
if (t instanceof tokens_1.AccessPathToken)
|
|
8593
|
+
if (t instanceof tokens_1.AccessPathToken && !(t.ap instanceof accesspaths_1.LazyAccessPath))
|
|
8152
8594
|
for (const [n, encl] of m)
|
|
8153
8595
|
(0, util_1.mapGetMap)(this.escapingToExternal, t.ap).set(n, encl);
|
|
8154
8596
|
}
|
|
@@ -11982,7 +12424,7 @@ var require_paths = __commonJS({
|
|
|
11982
12424
|
}
|
|
11983
12425
|
__name(isPathExistInArray, "isPathExistInArray");
|
|
11984
12426
|
function removeBestCandidate(candidates) {
|
|
11985
|
-
return candidates.sort((a, b) =>
|
|
12427
|
+
return candidates.sort((a, b) => a.totalCost - b.totalCost).shift();
|
|
11986
12428
|
}
|
|
11987
12429
|
__name(removeBestCandidate, "removeBestCandidate");
|
|
11988
12430
|
function dijkstra(g, source, removed) {
|
|
@@ -12572,8 +13014,9 @@ ${p} (${(0, vulnerabilities_1.getVulnerabilityId)(v)})`);
|
|
|
12572
13014
|
target.edges.push({ to, weight: 1 });
|
|
12573
13015
|
g.nodes.push(to);
|
|
12574
13016
|
g.targets = [to];
|
|
13017
|
+
const orderedSources = g.sources.toSorted((a, b) => (0, util_1.locationToStringWithFileAndEnd)(a.node?.loc, true).localeCompare((0, util_1.locationToStringWithFileAndEnd)(b.node?.loc, true)));
|
|
12575
13018
|
let i = 0;
|
|
12576
|
-
for (const source of
|
|
13019
|
+
for (const source of orderedSources) {
|
|
12577
13020
|
if (maxSources !== void 0 && i++ > maxSources)
|
|
12578
13021
|
break;
|
|
12579
13022
|
const t = logger_1.default.isVerboseEnabled() && new timer_1.default();
|
|
@@ -12732,17 +13175,9 @@ var require_apiexported = __commonJS({
|
|
|
12732
13175
|
return void 0;
|
|
12733
13176
|
}
|
|
12734
13177
|
__name(findFunctionAtLocation, "findFunctionAtLocation");
|
|
12735
|
-
function getReverseGraph(g) {
|
|
12736
|
-
const r = /* @__PURE__ */ new Map();
|
|
12737
|
-
for (const [from, tos] of g)
|
|
12738
|
-
for (const to of tos)
|
|
12739
|
-
(0, util_1.mapGetSet)(r, to).add(from);
|
|
12740
|
-
return r;
|
|
12741
|
-
}
|
|
12742
|
-
__name(getReverseGraph, "getReverseGraph");
|
|
12743
13178
|
function findReachingFunctions(f, fun) {
|
|
12744
|
-
const callers = getReverseGraph(f.functionToFunction);
|
|
12745
|
-
const requires = getReverseGraph(f.requireGraph);
|
|
13179
|
+
const callers = (0, util_1.getReverseGraph)(f.functionToFunction);
|
|
13180
|
+
const requires = (0, util_1.getReverseGraph)(f.requireGraph);
|
|
12746
13181
|
const r = /* @__PURE__ */ new Map();
|
|
12747
13182
|
const w = /* @__PURE__ */ new Set();
|
|
12748
13183
|
r.set(fun, /* @__PURE__ */ new Set());
|
|
@@ -12978,9 +13413,10 @@ var require_main = __commonJS({
|
|
|
12978
13413
|
var apiexported_1 = require_apiexported();
|
|
12979
13414
|
var merge_1 = require_merge();
|
|
12980
13415
|
var processmanager_1 = require_processmanager();
|
|
13416
|
+
var assert_1 = __importDefault(__require("assert"));
|
|
12981
13417
|
var semver_1 = __importDefault(require_semver2());
|
|
12982
13418
|
var ENGINES_NODE = require_package()?.engines?.node;
|
|
12983
|
-
commander_1.program.name("jelly").version(options_1.VERSION).addHelpText("before", options_1.COPYRIGHT).option("-b, --basedir <directory>", "base directory for files to analyze (default: auto-detect)").option("-f, --logfile <file>", "log to file (default: log to stdout)").option("-l, --loglevel <level>", "log level (debug/verbose/info/warn/error)", "info").option("-i, --timeout <seconds>", "limit analysis time").option("-a, --dataflow-html <file>", "save data-flow graph as HTML file").option("-m, --callgraph-html <file>", "save call graph as HTML file").option("-j, --callgraph-json <file>", "save call graph as JSON file").option("-s, --soundness <file>", "compare with dynamic call graph").option("-n, --graal-home <directory>", "home of graal-nodejs (default: $GRAAL_HOME)").option("-d, --dynamic <file>", "generate call graph dynamically, no static analysis").option("--approx", "enable approximate interpretation").option("--approx-only <file>", "perform approximate interpretation, no static analysis").option("--approx-load <file>", "use pre-computed approximate interpretation results").option("-p, --patterns <file...>", "files containing API usage patterns to detect").option("-v, --vulnerabilities <file>", "report vulnerability matches").option("--vulnerabilities-json <json>", "report vulnerability matches (patterns given as JSON string)").option("--include-packages <package...>", "include only dependencies in this list").option("--exclude-packages <package...>", "exclude dependencies in this list").option("--ignore-dependencies", "don't include dependencies in analysis").option("--ignore-unresolved", "don't report errors about unresolved modules").option("--npm-test <dir>", "run 'npm test' instead of 'node' (use with -d)").option("--callgraph", "report call graph").option("--tokens-json <file>", "save tokens for constraint variables as JSON file").option("--tokens", "report tokens for constraint variables").option("--largest", "report largest token sets and subset relations").option("--no-cycle-elimination", "disable cycle elimination").option("--no-natives", "disable nonessential models of native libraries").option("--test-graal", "test graal-nodejs (use with -d)").option("--no-print-progress", "don't print analysis progress information").option("--no-tty", "don't print solver progress for TTY").option("--warnings-unsupported", "print warnings about unsupported features").option("--gc", "enable garbage collection for more accurate memory usage reporting").option("--typescript", "enable TypeScript type inference (use with -p)").option("--api-usage", "report API usage of external packages (implies --ignore-dependencies)").option("--api-exported", "report API of modules").option("--find-access-paths <location>", "find access paths for source location (file:line)").option("--higher-order-functions", "report higher-order functions").option("--zeros", "report calls with zero callees and functions with zero callers").option("--exclude-entries <glob...>", "files to exclude when specifying entry directories").option("--tracked-modules <glob...>", "modules to track usage of (default: auto-detect)").option("--external-matches", "enable pattern matches from external code").option("--no-callgraph-implicit", "omit implicit calls in call graph").option("--no-callgraph-native", "omit native calls in call graph").option("--no-callgraph-require", "omit module loading in call graph").option("--no-callgraph-external", "omit heuristic external callbacks in call graph").option("--diagnostics", "report internal analysis diagnostics").option("--diagnostics-json <file>", "save analysis diagnostics in JSON file").option("--variable-kinds", "report constraint variable kinds").option("--max-waves <number>", "limit number of fixpoint waves").option("--max-indirections <number>", "limit number of function call and property write indirections").option("--full-indirection-bounding", "enable indirection bounding for method calls and property reads (use with --max-indirections)").option("--typescript-library-usage <file>", "save TypeScript library usage in JSON file, no analysis").option("--modules-only", "report reachable packages and modules only, no analysis").option("--compare-callgraphs", "compare two call graphs given as JSON files, no analysis").option("--reachability", "compare call graph reachability (use with -s or --compare-callgraphs)").option("--library", "assume program is a library (default: true if in node_modules)").option("--skip-tests", "skip files that look like tests").option("--no-patch-escaping", "disable patching using escape analysis").option("--patch-dynamics", "enable dynamic property access patching heuristic").option("--patch-method-calls", "enable method call patching heuristic").option("--no-patch-this", "disable 'this' patching heuristic").option("--
|
|
13419
|
+
commander_1.program.name("jelly").version(options_1.VERSION).addHelpText("before", options_1.COPYRIGHT).option("-b, --basedir <directory>", "base directory for files to analyze (default: auto-detect)").option("-f, --logfile <file>", "log to file (default: log to stdout)").option("-l, --loglevel <level>", "log level (debug/verbose/info/warn/error)", "info").option("-i, --timeout <seconds>", "limit analysis time").option("-a, --dataflow-html <file>", "save data-flow graph as HTML file").option("-m, --callgraph-html <file>", "save call graph as HTML file").option("-j, --callgraph-json <file>", "save call graph as JSON file").option("-s, --soundness <file>", "compare with dynamic call graph").option("-n, --graal-home <directory>", "home of graal-nodejs (default: $GRAAL_HOME)").option("-d, --dynamic <file>", "generate call graph dynamically, no static analysis").option("--approx", "enable approximate interpretation").option("--approx-only <file>", "perform approximate interpretation, no static analysis").option("--approx-load <file>", "use pre-computed approximate interpretation results").option("-p, --patterns <file...>", "files containing API usage patterns to detect").option("-v, --vulnerabilities <file>", "report vulnerability matches").option("--vulnerabilities-json <json>", "report vulnerability matches (patterns given as JSON string)").option("--include-packages <package...>", "include only dependencies in this list").option("--exclude-packages <package...>", "exclude dependencies in this list").option("--ignore-dependencies", "don't include dependencies in analysis").option("--ignore-unresolved", "don't report errors about unresolved modules").option("--npm-test <dir>", "run 'npm test' instead of 'node' (use with -d)").option("--callgraph", "report call graph").option("--tokens-json <file>", "save tokens for constraint variables as JSON file").option("--tokens", "report tokens for constraint variables").option("--largest", "report largest token sets and subset relations").option("--no-cycle-elimination", "disable cycle elimination").option("--no-natives", "disable nonessential models of native libraries").option("--test-graal", "test graal-nodejs (use with -d)").option("--no-print-progress", "don't print analysis progress information").option("--no-tty", "don't print solver progress for TTY").option("--warnings-unsupported", "print warnings about unsupported features").option("--gc", "enable garbage collection for more accurate memory usage reporting").option("--typescript", "enable TypeScript type inference (use with -p)").option("--api-usage", "report API usage of external packages (implies --ignore-dependencies)").option("--api-exported", "report API of modules").option("--find-access-paths <location>", "find access paths for source location (file:line)").option("--higher-order-functions", "report higher-order functions").option("--zeros", "report calls with zero callees and functions with zero callers").option("--exclude-entries <glob...>", "files to exclude when specifying entry directories").option("--tracked-modules <glob...>", "modules to track usage of (default: auto-detect)").option("--external-matches", "enable pattern matches from external code").option("--no-callgraph-implicit", "omit implicit calls in call graph").option("--no-callgraph-native", "omit native calls in call graph").option("--no-callgraph-require", "omit module loading in call graph").option("--no-callgraph-external", "omit heuristic external callbacks in call graph").option("--diagnostics", "report internal analysis diagnostics").option("--diagnostics-json <file>", "save analysis diagnostics in JSON file").option("--variable-kinds", "report constraint variable kinds").option("--max-waves <number>", "limit number of fixpoint waves").option("--max-indirections <number>", "limit number of function call and property write indirections").option("--full-indirection-bounding", "enable indirection bounding for method calls and property reads (use with --max-indirections)").option("--typescript-library-usage <file>", "save TypeScript library usage in JSON file, no analysis").option("--modules-only", "report reachable packages and modules only, no analysis").option("--compare-callgraphs", "compare two call graphs given as JSON files, no analysis").option("--reachability", "compare call graph reachability (use with -s or --compare-callgraphs)").option("--library", "assume program is a library (default: true if in node_modules)").option("--skip-tests", "skip files that look like tests").option("--no-patch-escaping", "disable patching using escape analysis").option("--patch-dynamics", "enable dynamic property access patching heuristic").option("--patch-method-calls", "enable method call patching heuristic").option("--no-patch-this", "disable 'this' patching heuristic").option("--proto", "enable model of assignments to the __proto__ property").option("--obj-spread", "enable model of spread syntax for object literals ({...obj})").option("--native-overwrites", "allow overwriting of native object properties").option("--ignore-imprecise-native-calls", "ignore imprecise native calls").option("--matches-json <file>", "save vulnerability pattern matches in JSON file").option("--reachable-json <file>", "save reachable packages and modules in JSON file").option("--callstacks-json <file>", "save vulnerability call stacks in JSON file").option("--vulnerabilities-full", "full report of vulnerabilities").option("--modules-json <file>", "save modules dependencies in JSON file").option("--lazy", "lazy analysis of modules").option("--lazy-cleanup", "lazily clean up redundant tokens for lazy module analysis").usage("[options] [files]").addHelpText("after", `
|
|
12984
13420
|
All modules reachable by require/import from the given files are included in the analysis
|
|
12985
13421
|
(except when using --ignore-dependencies, --include-packages or --exclude-packages).
|
|
12986
13422
|
If specifying directories instead of files, the files in the directories and their
|
|
@@ -13170,7 +13606,7 @@ Memory limit is ${(0, memory_1.getMemoryLimit)()}MB.${options_1.PKG ? "" : " Cha
|
|
|
13170
13606
|
}
|
|
13171
13607
|
if (options_1.options.vulnerabilities || options_1.options.vulnerabilitiesJson) {
|
|
13172
13608
|
if (options_1.options.vulnerabilities)
|
|
13173
|
-
logger_1.default.info(`Loading vulnerability
|
|
13609
|
+
logger_1.default.info(`Loading vulnerability descriptors from ${options_1.options.vulnerabilities}`);
|
|
13174
13610
|
vulnerabilityDetector = new vulnerabilitydetector_1.VulnerabilityDetector(JSON.parse(options_1.options.vulnerabilities ? (0, fs_1.readFileSync)(options_1.options.vulnerabilities, "utf8") : options_1.options.vulnerabilitiesJson));
|
|
13175
13611
|
const ps = vulnerabilityDetector.getPatterns();
|
|
13176
13612
|
(0, util_1.addAll)((0, patternloader_1.getGlobs)(ps), globs = globs ?? /* @__PURE__ */ new Set());
|
|
@@ -13178,6 +13614,12 @@ Memory limit is ${(0, memory_1.getMemoryLimit)()}MB.${options_1.PKG ? "" : " Cha
|
|
|
13178
13614
|
}
|
|
13179
13615
|
(0, options_1.setDefaultTrackedModules)(globs);
|
|
13180
13616
|
(0, options_1.setPatternProperties)(options_1.options.apiUsage ? void 0 : props ?? /* @__PURE__ */ new Set());
|
|
13617
|
+
if (options_1.options.lazy && !options_1.options.vulnerabilities && !options_1.options.vulnerabilitiesJson) {
|
|
13618
|
+
logger_1.default.error("Error: --lazy enabled but no vulnerabilities (use --vulnerabilities or --vulnerabilities-JSON)");
|
|
13619
|
+
process.exitCode = -1;
|
|
13620
|
+
return;
|
|
13621
|
+
}
|
|
13622
|
+
(0, assert_1.default)(!options_1.options.lazy || options_1.options.trackedModules);
|
|
13181
13623
|
const solver = new solver_1.default();
|
|
13182
13624
|
const a = solver.globalState;
|
|
13183
13625
|
a.vulnerabilities = vulnerabilityDetector;
|