@coana-tech/cli 14.12.159 → 14.12.160
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 +133 -89
- package/package.json +1 -1
- package/reachability-analyzers-cli.mjs +79 -64
- 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/cli.mjs
CHANGED
|
@@ -205220,55 +205220,34 @@ var Spinner = class _Spinner {
|
|
|
205220
205220
|
|
|
205221
205221
|
// ../utils/src/telemetry/telemetry-collector.ts
|
|
205222
205222
|
import { execFile } from "child_process";
|
|
205223
|
-
import { platform } from "
|
|
205223
|
+
import { platform } from "process";
|
|
205224
205224
|
import { promisify } from "util";
|
|
205225
205225
|
var execFileAsync = promisify(execFile);
|
|
205226
|
-
var TelemetryCollector = class {
|
|
205227
|
-
|
|
205228
|
-
|
|
205229
|
-
|
|
205230
|
-
|
|
205231
|
-
|
|
205232
|
-
|
|
205233
|
-
*/
|
|
205234
|
-
async collectChildProcessMetrics(pid) {
|
|
205235
|
-
if (!Number.isInteger(pid) || pid <= 0) {
|
|
205236
|
-
return void 0;
|
|
205237
|
-
}
|
|
205238
|
-
try {
|
|
205239
|
-
const currentPlatform = platform();
|
|
205240
|
-
if (currentPlatform === "darwin" || currentPlatform === "linux") {
|
|
205241
|
-
return await this.collectUnixProcessMetrics(pid);
|
|
205242
|
-
}
|
|
205243
|
-
return void 0;
|
|
205244
|
-
} catch {
|
|
205245
|
-
return void 0;
|
|
205246
|
-
}
|
|
205226
|
+
var TelemetryCollector = class _TelemetryCollector {
|
|
205227
|
+
constructor(pid) {
|
|
205228
|
+
this.pid = pid;
|
|
205229
|
+
}
|
|
205230
|
+
static create(pid) {
|
|
205231
|
+
if (!Number.isInteger(pid) || pid <= 0 || !["darwin", "linux"].includes(platform)) return void 0;
|
|
205232
|
+
return new _TelemetryCollector(pid);
|
|
205247
205233
|
}
|
|
205248
205234
|
/**
|
|
205249
205235
|
* Collect metrics for a Unix-like system (macOS, Linux) using ps command.
|
|
205250
205236
|
*/
|
|
205251
|
-
async
|
|
205237
|
+
async collectChildProcessMetrics() {
|
|
205252
205238
|
try {
|
|
205253
|
-
const { stdout } = await execFileAsync("ps", ["-o", "rss=,pcpu=", "-p", String(pid)], {
|
|
205239
|
+
const { stdout } = await execFileAsync("ps", ["-o", "rss=,pcpu=", "-p", String(this.pid)], {
|
|
205254
205240
|
timeout: 5e3
|
|
205255
205241
|
});
|
|
205256
|
-
const
|
|
205257
|
-
if (
|
|
205258
|
-
return void 0;
|
|
205259
|
-
}
|
|
205260
|
-
const parts = trimmed.split(/\s+/);
|
|
205261
|
-
if (parts.length < 2) {
|
|
205262
|
-
return void 0;
|
|
205263
|
-
}
|
|
205242
|
+
const parts = stdout.trim().split(/\s+/);
|
|
205243
|
+
if (parts.length < 2) return void 0;
|
|
205264
205244
|
const rssKb = parseInt(parts[0], 10);
|
|
205265
205245
|
const cpuPercent = parseFloat(parts[1]);
|
|
205266
|
-
if (isNaN(rssKb) || isNaN(cpuPercent))
|
|
205267
|
-
return void 0;
|
|
205268
|
-
}
|
|
205269
|
-
const rssBytes = rssKb * 1024;
|
|
205246
|
+
if (isNaN(rssKb) || isNaN(cpuPercent)) return void 0;
|
|
205270
205247
|
return {
|
|
205271
|
-
rss:
|
|
205248
|
+
rss: rssKb * 1024,
|
|
205249
|
+
// Convert KB to bytes
|
|
205250
|
+
// Note: cpuPercent can exceed 100% on multi-core systems (e.g., 250% = 2.5 cores used)
|
|
205272
205251
|
cpuPercent
|
|
205273
205252
|
};
|
|
205274
205253
|
} catch {
|
|
@@ -205376,14 +205355,14 @@ function startHeartbeat(options) {
|
|
|
205376
205355
|
return () => clearInterval(timer);
|
|
205377
205356
|
}
|
|
205378
205357
|
var DEFAULT_TELEMETRY_INTERVAL_MS = 5e3;
|
|
205379
|
-
function startTelemetry(
|
|
205380
|
-
const collector =
|
|
205358
|
+
function startTelemetry(subprocess, handler) {
|
|
205359
|
+
const collector = TelemetryCollector.create(subprocess.pid);
|
|
205360
|
+
if (!collector) return;
|
|
205361
|
+
handler.onInit?.(subprocess);
|
|
205381
205362
|
const intervalMs = handler.intervalMs ?? DEFAULT_TELEMETRY_INTERVAL_MS;
|
|
205382
205363
|
const collectAndReport = async () => {
|
|
205383
|
-
const metrics = await collector.collectChildProcessMetrics(
|
|
205384
|
-
if (metrics)
|
|
205385
|
-
handler.onTelemetry(metrics);
|
|
205386
|
-
}
|
|
205364
|
+
const metrics = await collector.collectChildProcessMetrics();
|
|
205365
|
+
if (metrics) handler.onTelemetry(metrics);
|
|
205387
205366
|
};
|
|
205388
205367
|
collectAndReport().catch((err) => {
|
|
205389
205368
|
logger.debug("Initial telemetry collection failed:", err);
|
|
@@ -205395,6 +205374,48 @@ function startTelemetry(pid, handler) {
|
|
|
205395
205374
|
timer.unref?.();
|
|
205396
205375
|
return () => clearInterval(timer);
|
|
205397
205376
|
}
|
|
205377
|
+
function wrapWithMemoryLimit(cmd, options) {
|
|
205378
|
+
const memoryLimitKiB = Math.ceil(options.memoryLimitInMB * 1024);
|
|
205379
|
+
if (memoryLimitKiB <= 0)
|
|
205380
|
+
throw new Error(`memoryLimitInMB * 1024 must be a positive number, got: ${memoryLimitKiB}`);
|
|
205381
|
+
switch (process.platform) {
|
|
205382
|
+
case "darwin":
|
|
205383
|
+
{
|
|
205384
|
+
const prevHandler = options.telemetryHandler;
|
|
205385
|
+
let subprocess;
|
|
205386
|
+
options.telemetryHandler = {
|
|
205387
|
+
intervalMs: prevHandler?.intervalMs ?? 2e3,
|
|
205388
|
+
onInit: (sp) => {
|
|
205389
|
+
subprocess = sp;
|
|
205390
|
+
prevHandler?.onInit?.(sp);
|
|
205391
|
+
},
|
|
205392
|
+
onTelemetry(metrics) {
|
|
205393
|
+
if (subprocess?.exitCode === null && metrics.rss >= memoryLimitKiB * 1024) {
|
|
205394
|
+
logger.debug(
|
|
205395
|
+
`Memory limit of ${options.memoryLimitInMB} MiB exceeded (RSS: ${(metrics.rss / 1024 / 1024).toFixed(
|
|
205396
|
+
2
|
|
205397
|
+
)} MiB). Terminating process.`
|
|
205398
|
+
);
|
|
205399
|
+
subprocess.kill(options.killSignal ?? "SIGTERM");
|
|
205400
|
+
subprocess = void 0;
|
|
205401
|
+
}
|
|
205402
|
+
prevHandler?.onTelemetry(metrics);
|
|
205403
|
+
}
|
|
205404
|
+
};
|
|
205405
|
+
}
|
|
205406
|
+
break;
|
|
205407
|
+
case "linux":
|
|
205408
|
+
return [
|
|
205409
|
+
"sh",
|
|
205410
|
+
...typeof cmd === "string" ? ["-c", `ulimit -v ${memoryLimitKiB} && eval "$1"`, "_", cmd] : ["-c", `ulimit -v ${memoryLimitKiB} && exec "$@"`, "_", ...cmd]
|
|
205411
|
+
];
|
|
205412
|
+
default:
|
|
205413
|
+
logger.debug(
|
|
205414
|
+
`Memory limit enforcement is not supported on platform: ${process.platform}. Ignoring memory limit option.`
|
|
205415
|
+
);
|
|
205416
|
+
}
|
|
205417
|
+
return cmd;
|
|
205418
|
+
}
|
|
205398
205419
|
async function execNeverFail(cmd, dir, options) {
|
|
205399
205420
|
const stopHeartbeat = options?.heartbeat ? startHeartbeat(options.heartbeat) : void 0;
|
|
205400
205421
|
let stopTelemetry;
|
|
@@ -205404,6 +205425,8 @@ async function execNeverFail(cmd, dir, options) {
|
|
|
205404
205425
|
analyzerTelemetryServer = new AnalyzerTelemetryServer(options.analyzerTelemetryHandler);
|
|
205405
205426
|
analyzerTelemetryFilePath = await analyzerTelemetryServer.start();
|
|
205406
205427
|
}
|
|
205428
|
+
if (options?.memoryLimitInMB !== void 0)
|
|
205429
|
+
cmd = wrapWithMemoryLimit(cmd, options);
|
|
205407
205430
|
try {
|
|
205408
205431
|
return await new Promise((resolve45) => {
|
|
205409
205432
|
let args2;
|
|
@@ -205418,9 +205441,8 @@ async function execNeverFail(cmd, dir, options) {
|
|
|
205418
205441
|
resolve45({ error, stdout, stderr });
|
|
205419
205442
|
}
|
|
205420
205443
|
);
|
|
205421
|
-
if (options?.telemetryHandler && childProcess.pid)
|
|
205422
|
-
stopTelemetry = startTelemetry(childProcess
|
|
205423
|
-
}
|
|
205444
|
+
if (options?.telemetryHandler && childProcess.pid)
|
|
205445
|
+
stopTelemetry = startTelemetry(childProcess, options.telemetryHandler);
|
|
205424
205446
|
if (options?.pipe) {
|
|
205425
205447
|
childProcess.stdout?.on("data", (data2) => {
|
|
205426
205448
|
Spinner.instance().suspend(() => {
|
|
@@ -224295,55 +224317,38 @@ var Spinner2 = class _Spinner {
|
|
|
224295
224317
|
|
|
224296
224318
|
// ../utils/dist/telemetry/telemetry-collector.js
|
|
224297
224319
|
import { execFile as execFile3 } from "child_process";
|
|
224298
|
-
import { platform as platform7 } from "
|
|
224320
|
+
import { platform as platform7 } from "process";
|
|
224299
224321
|
import { promisify as promisify2 } from "util";
|
|
224300
224322
|
var execFileAsync2 = promisify2(execFile3);
|
|
224301
|
-
var TelemetryCollector2 = class {
|
|
224302
|
-
|
|
224303
|
-
|
|
224304
|
-
|
|
224305
|
-
|
|
224306
|
-
|
|
224307
|
-
|
|
224308
|
-
*/
|
|
224309
|
-
async collectChildProcessMetrics(pid) {
|
|
224310
|
-
if (!Number.isInteger(pid) || pid <= 0) {
|
|
224311
|
-
return void 0;
|
|
224312
|
-
}
|
|
224313
|
-
try {
|
|
224314
|
-
const currentPlatform = platform7();
|
|
224315
|
-
if (currentPlatform === "darwin" || currentPlatform === "linux") {
|
|
224316
|
-
return await this.collectUnixProcessMetrics(pid);
|
|
224317
|
-
}
|
|
224318
|
-
return void 0;
|
|
224319
|
-
} catch {
|
|
224323
|
+
var TelemetryCollector2 = class _TelemetryCollector {
|
|
224324
|
+
pid;
|
|
224325
|
+
constructor(pid) {
|
|
224326
|
+
this.pid = pid;
|
|
224327
|
+
}
|
|
224328
|
+
static create(pid) {
|
|
224329
|
+
if (!Number.isInteger(pid) || pid <= 0 || !["darwin", "linux"].includes(platform7))
|
|
224320
224330
|
return void 0;
|
|
224321
|
-
|
|
224331
|
+
return new _TelemetryCollector(pid);
|
|
224322
224332
|
}
|
|
224323
224333
|
/**
|
|
224324
224334
|
* Collect metrics for a Unix-like system (macOS, Linux) using ps command.
|
|
224325
224335
|
*/
|
|
224326
|
-
async
|
|
224336
|
+
async collectChildProcessMetrics() {
|
|
224327
224337
|
try {
|
|
224328
|
-
const { stdout } = await execFileAsync2("ps", ["-o", "rss=,pcpu=", "-p", String(pid)], {
|
|
224338
|
+
const { stdout } = await execFileAsync2("ps", ["-o", "rss=,pcpu=", "-p", String(this.pid)], {
|
|
224329
224339
|
timeout: 5e3
|
|
224330
224340
|
});
|
|
224331
|
-
const
|
|
224332
|
-
if (
|
|
224333
|
-
return void 0;
|
|
224334
|
-
}
|
|
224335
|
-
const parts = trimmed.split(/\s+/);
|
|
224336
|
-
if (parts.length < 2) {
|
|
224341
|
+
const parts = stdout.trim().split(/\s+/);
|
|
224342
|
+
if (parts.length < 2)
|
|
224337
224343
|
return void 0;
|
|
224338
|
-
}
|
|
224339
224344
|
const rssKb = parseInt(parts[0], 10);
|
|
224340
224345
|
const cpuPercent = parseFloat(parts[1]);
|
|
224341
|
-
if (isNaN(rssKb) || isNaN(cpuPercent))
|
|
224346
|
+
if (isNaN(rssKb) || isNaN(cpuPercent))
|
|
224342
224347
|
return void 0;
|
|
224343
|
-
}
|
|
224344
|
-
const rssBytes = rssKb * 1024;
|
|
224345
224348
|
return {
|
|
224346
|
-
rss:
|
|
224349
|
+
rss: rssKb * 1024,
|
|
224350
|
+
// Convert KB to bytes
|
|
224351
|
+
// Note: cpuPercent can exceed 100% on multi-core systems (e.g., 250% = 2.5 cores used)
|
|
224347
224352
|
cpuPercent
|
|
224348
224353
|
};
|
|
224349
224354
|
} catch {
|
|
@@ -224452,14 +224457,16 @@ function startHeartbeat2(options) {
|
|
|
224452
224457
|
return () => clearInterval(timer);
|
|
224453
224458
|
}
|
|
224454
224459
|
var DEFAULT_TELEMETRY_INTERVAL_MS2 = 5e3;
|
|
224455
|
-
function startTelemetry2(
|
|
224456
|
-
const collector =
|
|
224460
|
+
function startTelemetry2(subprocess, handler) {
|
|
224461
|
+
const collector = TelemetryCollector2.create(subprocess.pid);
|
|
224462
|
+
if (!collector)
|
|
224463
|
+
return;
|
|
224464
|
+
handler.onInit?.(subprocess);
|
|
224457
224465
|
const intervalMs = handler.intervalMs ?? DEFAULT_TELEMETRY_INTERVAL_MS2;
|
|
224458
224466
|
const collectAndReport = async () => {
|
|
224459
|
-
const metrics = await collector.collectChildProcessMetrics(
|
|
224460
|
-
if (metrics)
|
|
224467
|
+
const metrics = await collector.collectChildProcessMetrics();
|
|
224468
|
+
if (metrics)
|
|
224461
224469
|
handler.onTelemetry(metrics);
|
|
224462
|
-
}
|
|
224463
224470
|
};
|
|
224464
224471
|
collectAndReport().catch((err) => {
|
|
224465
224472
|
logger.debug("Initial telemetry collection failed:", err);
|
|
@@ -224471,6 +224478,42 @@ function startTelemetry2(pid, handler) {
|
|
|
224471
224478
|
timer.unref?.();
|
|
224472
224479
|
return () => clearInterval(timer);
|
|
224473
224480
|
}
|
|
224481
|
+
function wrapWithMemoryLimit2(cmd, options) {
|
|
224482
|
+
const memoryLimitKiB = Math.ceil(options.memoryLimitInMB * 1024);
|
|
224483
|
+
if (memoryLimitKiB <= 0)
|
|
224484
|
+
throw new Error(`memoryLimitInMB * 1024 must be a positive number, got: ${memoryLimitKiB}`);
|
|
224485
|
+
switch (process.platform) {
|
|
224486
|
+
case "darwin":
|
|
224487
|
+
{
|
|
224488
|
+
const prevHandler = options.telemetryHandler;
|
|
224489
|
+
let subprocess;
|
|
224490
|
+
options.telemetryHandler = {
|
|
224491
|
+
intervalMs: prevHandler?.intervalMs ?? 2e3,
|
|
224492
|
+
onInit: (sp) => {
|
|
224493
|
+
subprocess = sp;
|
|
224494
|
+
prevHandler?.onInit?.(sp);
|
|
224495
|
+
},
|
|
224496
|
+
onTelemetry(metrics) {
|
|
224497
|
+
if (subprocess?.exitCode === null && metrics.rss >= memoryLimitKiB * 1024) {
|
|
224498
|
+
logger.debug(`Memory limit of ${options.memoryLimitInMB} MiB exceeded (RSS: ${(metrics.rss / 1024 / 1024).toFixed(2)} MiB). Terminating process.`);
|
|
224499
|
+
subprocess.kill(options.killSignal ?? "SIGTERM");
|
|
224500
|
+
subprocess = void 0;
|
|
224501
|
+
}
|
|
224502
|
+
prevHandler?.onTelemetry(metrics);
|
|
224503
|
+
}
|
|
224504
|
+
};
|
|
224505
|
+
}
|
|
224506
|
+
break;
|
|
224507
|
+
case "linux":
|
|
224508
|
+
return [
|
|
224509
|
+
"sh",
|
|
224510
|
+
...typeof cmd === "string" ? ["-c", `ulimit -v ${memoryLimitKiB} && eval "$1"`, "_", cmd] : ["-c", `ulimit -v ${memoryLimitKiB} && exec "$@"`, "_", ...cmd]
|
|
224511
|
+
];
|
|
224512
|
+
default:
|
|
224513
|
+
logger.debug(`Memory limit enforcement is not supported on platform: ${process.platform}. Ignoring memory limit option.`);
|
|
224514
|
+
}
|
|
224515
|
+
return cmd;
|
|
224516
|
+
}
|
|
224474
224517
|
async function execNeverFail3(cmd, dir, options) {
|
|
224475
224518
|
const stopHeartbeat = options?.heartbeat ? startHeartbeat2(options.heartbeat) : void 0;
|
|
224476
224519
|
let stopTelemetry;
|
|
@@ -224480,6 +224523,8 @@ async function execNeverFail3(cmd, dir, options) {
|
|
|
224480
224523
|
analyzerTelemetryServer = new AnalyzerTelemetryServer2(options.analyzerTelemetryHandler);
|
|
224481
224524
|
analyzerTelemetryFilePath = await analyzerTelemetryServer.start();
|
|
224482
224525
|
}
|
|
224526
|
+
if (options?.memoryLimitInMB !== void 0)
|
|
224527
|
+
cmd = wrapWithMemoryLimit2(cmd, options);
|
|
224483
224528
|
try {
|
|
224484
224529
|
return await new Promise((resolve45) => {
|
|
224485
224530
|
let args2;
|
|
@@ -224490,9 +224535,8 @@ async function execNeverFail3(cmd, dir, options) {
|
|
|
224490
224535
|
const childProcess = execFile4(cmd, args2, { ...options, env, cwd: dir, maxBuffer: 1024 * 1024 * 1024, shell: args2 === void 0, timeout }, (error, stdout, stderr) => {
|
|
224491
224536
|
resolve45({ error, stdout, stderr });
|
|
224492
224537
|
});
|
|
224493
|
-
if (options?.telemetryHandler && childProcess.pid)
|
|
224494
|
-
stopTelemetry = startTelemetry2(childProcess
|
|
224495
|
-
}
|
|
224538
|
+
if (options?.telemetryHandler && childProcess.pid)
|
|
224539
|
+
stopTelemetry = startTelemetry2(childProcess, options.telemetryHandler);
|
|
224496
224540
|
if (options?.pipe) {
|
|
224497
224541
|
childProcess.stdout?.on("data", (data2) => {
|
|
224498
224542
|
Spinner2.instance().suspend(() => {
|
|
@@ -250903,7 +250947,7 @@ async function onlineScan(dependencyTree, apiKey, timeout) {
|
|
|
250903
250947
|
}
|
|
250904
250948
|
|
|
250905
250949
|
// dist/version.js
|
|
250906
|
-
var version3 = "14.12.
|
|
250950
|
+
var version3 = "14.12.160";
|
|
250907
250951
|
|
|
250908
250952
|
// dist/cli-core.js
|
|
250909
250953
|
var { mapValues, omit, partition, pickBy: pickBy2 } = import_lodash15.default;
|
package/package.json
CHANGED
|
@@ -80900,55 +80900,34 @@ import { execFile as execFile2 } from "child_process";
|
|
|
80900
80900
|
|
|
80901
80901
|
// ../utils/src/telemetry/telemetry-collector.ts
|
|
80902
80902
|
import { execFile } from "child_process";
|
|
80903
|
-
import { platform } from "
|
|
80903
|
+
import { platform } from "process";
|
|
80904
80904
|
import { promisify } from "util";
|
|
80905
80905
|
var execFileAsync = promisify(execFile);
|
|
80906
|
-
var TelemetryCollector = class {
|
|
80907
|
-
|
|
80908
|
-
|
|
80909
|
-
|
|
80910
|
-
|
|
80911
|
-
|
|
80912
|
-
|
|
80913
|
-
*/
|
|
80914
|
-
async collectChildProcessMetrics(pid) {
|
|
80915
|
-
if (!Number.isInteger(pid) || pid <= 0) {
|
|
80916
|
-
return void 0;
|
|
80917
|
-
}
|
|
80918
|
-
try {
|
|
80919
|
-
const currentPlatform = platform();
|
|
80920
|
-
if (currentPlatform === "darwin" || currentPlatform === "linux") {
|
|
80921
|
-
return await this.collectUnixProcessMetrics(pid);
|
|
80922
|
-
}
|
|
80923
|
-
return void 0;
|
|
80924
|
-
} catch {
|
|
80925
|
-
return void 0;
|
|
80926
|
-
}
|
|
80906
|
+
var TelemetryCollector = class _TelemetryCollector {
|
|
80907
|
+
constructor(pid) {
|
|
80908
|
+
this.pid = pid;
|
|
80909
|
+
}
|
|
80910
|
+
static create(pid) {
|
|
80911
|
+
if (!Number.isInteger(pid) || pid <= 0 || !["darwin", "linux"].includes(platform)) return void 0;
|
|
80912
|
+
return new _TelemetryCollector(pid);
|
|
80927
80913
|
}
|
|
80928
80914
|
/**
|
|
80929
80915
|
* Collect metrics for a Unix-like system (macOS, Linux) using ps command.
|
|
80930
80916
|
*/
|
|
80931
|
-
async
|
|
80917
|
+
async collectChildProcessMetrics() {
|
|
80932
80918
|
try {
|
|
80933
|
-
const { stdout } = await execFileAsync("ps", ["-o", "rss=,pcpu=", "-p", String(pid)], {
|
|
80919
|
+
const { stdout } = await execFileAsync("ps", ["-o", "rss=,pcpu=", "-p", String(this.pid)], {
|
|
80934
80920
|
timeout: 5e3
|
|
80935
80921
|
});
|
|
80936
|
-
const
|
|
80937
|
-
if (
|
|
80938
|
-
return void 0;
|
|
80939
|
-
}
|
|
80940
|
-
const parts = trimmed.split(/\s+/);
|
|
80941
|
-
if (parts.length < 2) {
|
|
80942
|
-
return void 0;
|
|
80943
|
-
}
|
|
80922
|
+
const parts = stdout.trim().split(/\s+/);
|
|
80923
|
+
if (parts.length < 2) return void 0;
|
|
80944
80924
|
const rssKb = parseInt(parts[0], 10);
|
|
80945
80925
|
const cpuPercent = parseFloat(parts[1]);
|
|
80946
|
-
if (isNaN(rssKb) || isNaN(cpuPercent))
|
|
80947
|
-
return void 0;
|
|
80948
|
-
}
|
|
80949
|
-
const rssBytes = rssKb * 1024;
|
|
80926
|
+
if (isNaN(rssKb) || isNaN(cpuPercent)) return void 0;
|
|
80950
80927
|
return {
|
|
80951
|
-
rss:
|
|
80928
|
+
rss: rssKb * 1024,
|
|
80929
|
+
// Convert KB to bytes
|
|
80930
|
+
// Note: cpuPercent can exceed 100% on multi-core systems (e.g., 250% = 2.5 cores used)
|
|
80952
80931
|
cpuPercent
|
|
80953
80932
|
};
|
|
80954
80933
|
} catch {
|
|
@@ -81053,14 +81032,14 @@ function startHeartbeat(options) {
|
|
|
81053
81032
|
return () => clearInterval(timer);
|
|
81054
81033
|
}
|
|
81055
81034
|
var DEFAULT_TELEMETRY_INTERVAL_MS = 5e3;
|
|
81056
|
-
function startTelemetry(
|
|
81057
|
-
const collector =
|
|
81035
|
+
function startTelemetry(subprocess, handler) {
|
|
81036
|
+
const collector = TelemetryCollector.create(subprocess.pid);
|
|
81037
|
+
if (!collector) return;
|
|
81038
|
+
handler.onInit?.(subprocess);
|
|
81058
81039
|
const intervalMs = handler.intervalMs ?? DEFAULT_TELEMETRY_INTERVAL_MS;
|
|
81059
81040
|
const collectAndReport = async () => {
|
|
81060
|
-
const metrics = await collector.collectChildProcessMetrics(
|
|
81061
|
-
if (metrics)
|
|
81062
|
-
handler.onTelemetry(metrics);
|
|
81063
|
-
}
|
|
81041
|
+
const metrics = await collector.collectChildProcessMetrics();
|
|
81042
|
+
if (metrics) handler.onTelemetry(metrics);
|
|
81064
81043
|
};
|
|
81065
81044
|
collectAndReport().catch((err) => {
|
|
81066
81045
|
logger.debug("Initial telemetry collection failed:", err);
|
|
@@ -81072,6 +81051,48 @@ function startTelemetry(pid, handler) {
|
|
|
81072
81051
|
timer.unref?.();
|
|
81073
81052
|
return () => clearInterval(timer);
|
|
81074
81053
|
}
|
|
81054
|
+
function wrapWithMemoryLimit(cmd, options) {
|
|
81055
|
+
const memoryLimitKiB = Math.ceil(options.memoryLimitInMB * 1024);
|
|
81056
|
+
if (memoryLimitKiB <= 0)
|
|
81057
|
+
throw new Error(`memoryLimitInMB * 1024 must be a positive number, got: ${memoryLimitKiB}`);
|
|
81058
|
+
switch (process.platform) {
|
|
81059
|
+
case "darwin":
|
|
81060
|
+
{
|
|
81061
|
+
const prevHandler = options.telemetryHandler;
|
|
81062
|
+
let subprocess;
|
|
81063
|
+
options.telemetryHandler = {
|
|
81064
|
+
intervalMs: prevHandler?.intervalMs ?? 2e3,
|
|
81065
|
+
onInit: (sp) => {
|
|
81066
|
+
subprocess = sp;
|
|
81067
|
+
prevHandler?.onInit?.(sp);
|
|
81068
|
+
},
|
|
81069
|
+
onTelemetry(metrics) {
|
|
81070
|
+
if (subprocess?.exitCode === null && metrics.rss >= memoryLimitKiB * 1024) {
|
|
81071
|
+
logger.debug(
|
|
81072
|
+
`Memory limit of ${options.memoryLimitInMB} MiB exceeded (RSS: ${(metrics.rss / 1024 / 1024).toFixed(
|
|
81073
|
+
2
|
|
81074
|
+
)} MiB). Terminating process.`
|
|
81075
|
+
);
|
|
81076
|
+
subprocess.kill(options.killSignal ?? "SIGTERM");
|
|
81077
|
+
subprocess = void 0;
|
|
81078
|
+
}
|
|
81079
|
+
prevHandler?.onTelemetry(metrics);
|
|
81080
|
+
}
|
|
81081
|
+
};
|
|
81082
|
+
}
|
|
81083
|
+
break;
|
|
81084
|
+
case "linux":
|
|
81085
|
+
return [
|
|
81086
|
+
"sh",
|
|
81087
|
+
...typeof cmd === "string" ? ["-c", `ulimit -v ${memoryLimitKiB} && eval "$1"`, "_", cmd] : ["-c", `ulimit -v ${memoryLimitKiB} && exec "$@"`, "_", ...cmd]
|
|
81088
|
+
];
|
|
81089
|
+
default:
|
|
81090
|
+
logger.debug(
|
|
81091
|
+
`Memory limit enforcement is not supported on platform: ${process.platform}. Ignoring memory limit option.`
|
|
81092
|
+
);
|
|
81093
|
+
}
|
|
81094
|
+
return cmd;
|
|
81095
|
+
}
|
|
81075
81096
|
async function execNeverFail(cmd, dir, options) {
|
|
81076
81097
|
const stopHeartbeat = options?.heartbeat ? startHeartbeat(options.heartbeat) : void 0;
|
|
81077
81098
|
let stopTelemetry;
|
|
@@ -81081,6 +81102,8 @@ async function execNeverFail(cmd, dir, options) {
|
|
|
81081
81102
|
analyzerTelemetryServer = new AnalyzerTelemetryServer(options.analyzerTelemetryHandler);
|
|
81082
81103
|
analyzerTelemetryFilePath = await analyzerTelemetryServer.start();
|
|
81083
81104
|
}
|
|
81105
|
+
if (options?.memoryLimitInMB !== void 0)
|
|
81106
|
+
cmd = wrapWithMemoryLimit(cmd, options);
|
|
81084
81107
|
try {
|
|
81085
81108
|
return await new Promise((resolve23) => {
|
|
81086
81109
|
let args;
|
|
@@ -81095,9 +81118,8 @@ async function execNeverFail(cmd, dir, options) {
|
|
|
81095
81118
|
resolve23({ error, stdout, stderr });
|
|
81096
81119
|
}
|
|
81097
81120
|
);
|
|
81098
|
-
if (options?.telemetryHandler && childProcess.pid)
|
|
81099
|
-
stopTelemetry = startTelemetry(childProcess
|
|
81100
|
-
}
|
|
81121
|
+
if (options?.telemetryHandler && childProcess.pid)
|
|
81122
|
+
stopTelemetry = startTelemetry(childProcess, options.telemetryHandler);
|
|
81101
81123
|
if (options?.pipe) {
|
|
81102
81124
|
childProcess.stdout?.on("data", (data2) => {
|
|
81103
81125
|
Spinner.instance().suspend(() => {
|
|
@@ -111156,7 +111178,8 @@ var GoCodeAwareVulnerabilityScanner = class {
|
|
|
111156
111178
|
${this.projectDir} ${vulnAccPaths}`, void 0, {
|
|
111157
111179
|
timeout: timeoutInSeconds * 1e3,
|
|
111158
111180
|
killSignal: "SIGKILL",
|
|
111159
|
-
|
|
111181
|
+
memoryLimitInMB,
|
|
111182
|
+
env: memoryLimitInMB ? { ...process.env, GOMEMLIMIT: `${Math.max(Math.ceil(memoryLimitInMB - 256), 0)}MiB` } : void 0,
|
|
111160
111183
|
heartbeat: HEARTBEATS.go,
|
|
111161
111184
|
telemetryHandler,
|
|
111162
111185
|
analyzerTelemetryHandler
|
|
@@ -112033,16 +112056,6 @@ function getVersion(analysisName) {
|
|
|
112033
112056
|
|
|
112034
112057
|
// dist/whole-program-code-aware-vulnerability-scanner/python/python-code-aware-vulnerability-scanner.js
|
|
112035
112058
|
var { omit, once: once3, pick, sortedUniq, uniqBy } = import_lodash14.default;
|
|
112036
|
-
var memlimitWrapper = `import sys, runpy, resource
|
|
112037
|
-
if memory_limit := int(sys.argv.pop(1)):
|
|
112038
|
-
try:
|
|
112039
|
-
resource.setrlimit(resource.RLIMIT_AS, (memory_limit * 1024 ** 2, resource.RLIM_INFINITY))
|
|
112040
|
-
except ValueError as e:
|
|
112041
|
-
# If we're running on PyPy, memory is bounded by PYPY_GC_MAX env var
|
|
112042
|
-
if sys.implementation.name != "pypy":
|
|
112043
|
-
print("ERROR: Failed to set memory limit", e, file=sys.stderr)
|
|
112044
|
-
runpy.run_module("mambalade", alter_sys=True)
|
|
112045
|
-
`;
|
|
112046
112059
|
var PythonCodeAwareVulnerabilityScanner = class {
|
|
112047
112060
|
state;
|
|
112048
112061
|
projectDir;
|
|
@@ -112071,10 +112084,10 @@ var PythonCodeAwareVulnerabilityScanner = class {
|
|
|
112071
112084
|
this.mambaladeVenvPath ??= await setupMambalade();
|
|
112072
112085
|
logger.info("Started instantiating Python code-aware analysis");
|
|
112073
112086
|
logger.debug(`Trying to find files to analyze from projectDir: ${this.projectDir}`);
|
|
112074
|
-
const { rootWorkingDir, reachabilityAnalysisOptions } = this.state;
|
|
112087
|
+
const { rootWorkingDir, reachabilityAnalysisOptions: { excludeDirs, memoryLimitInMB } } = this.state;
|
|
112075
112088
|
let filesToAnalyze = await findFilesToAnalyze(this.projectDir);
|
|
112076
|
-
if (
|
|
112077
|
-
filesToAnalyze = excludeFiles(rootWorkingDir, this.projectDir, filesToAnalyze,
|
|
112089
|
+
if (excludeDirs)
|
|
112090
|
+
filesToAnalyze = excludeFiles(rootWorkingDir, this.projectDir, filesToAnalyze, excludeDirs);
|
|
112078
112091
|
logger.info(`Found ${filesToAnalyze.length} files to analyze`);
|
|
112079
112092
|
logger.debug("%O", filesToAnalyze);
|
|
112080
112093
|
if (filesToAnalyze.length === 0)
|
|
@@ -112097,7 +112110,7 @@ var PythonCodeAwareVulnerabilityScanner = class {
|
|
|
112097
112110
|
const reachedPackagesOutputFile = join17(tmpDir, "reached-packages.json");
|
|
112098
112111
|
const pythonExecutable = join17(this.mambaladeVenvPath, "bin", "python");
|
|
112099
112112
|
const mambaladeArgs = cmdt`\
|
|
112100
|
-
${pythonExecutable} -
|
|
112113
|
+
${pythonExecutable} -m mambalade
|
|
112101
112114
|
--vulnerabilities ${vulnAccPaths}
|
|
112102
112115
|
--unsound-class-decorators --context-sensitivity=heuristics
|
|
112103
112116
|
--path ${this.virtualEnvInfo.virtualEnvPathToSitePackages}
|
|
@@ -112111,10 +112124,11 @@ var PythonCodeAwareVulnerabilityScanner = class {
|
|
|
112111
112124
|
${filesToAnalyze}`;
|
|
112112
112125
|
try {
|
|
112113
112126
|
const { stderr } = await exec2(mambaladeArgs, this.projectDir, {
|
|
112114
|
-
stdin: memlimitWrapper,
|
|
112115
112127
|
env: {
|
|
112116
112128
|
...process.env,
|
|
112117
|
-
|
|
112129
|
+
// Set PyPy-specific the memory limit 256MiB lower than the overall memory limit
|
|
112130
|
+
// to (hopefully) handle OOM gracefully within mambalade (instead of the OS killing the process).
|
|
112131
|
+
PYPY_GC_MAX: `${memoryLimitInMB ? Math.max(Math.ceil(memoryLimitInMB - 256), 1) : 0}MB`
|
|
112118
112132
|
},
|
|
112119
112133
|
// Forcefully kill the process if the internal timeout mechanism fails.
|
|
112120
112134
|
// Use SIGKILL to ensure termination even if the process is unresponsive.
|
|
@@ -112122,7 +112136,8 @@ var PythonCodeAwareVulnerabilityScanner = class {
|
|
|
112122
112136
|
killSignal: "SIGKILL",
|
|
112123
112137
|
heartbeat: HEARTBEATS.python,
|
|
112124
112138
|
telemetryHandler,
|
|
112125
|
-
analyzerTelemetryHandler
|
|
112139
|
+
analyzerTelemetryHandler,
|
|
112140
|
+
memoryLimitInMB
|
|
112126
112141
|
});
|
|
112127
112142
|
logger.debug("Done running mambalade");
|
|
112128
112143
|
const errors = stderr.split("\n").filter((line) => line.startsWith("ERROR:") && !/^ERROR: Excluded distribution/.test(line));
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|