Commit d1960949bb0 for nodejs

commit d1960949bb0710df25ca00320b2e51a69ef73238
Author: James M Snell <jasnell@gmail.com>
Date:   Sat Sep 19 17:20:15 2026 +0000

    benchmark: protect against accidental fork bomb

    Signed-off-by: James M Snell <jasnell@gmail.com>
    Assisted-by: Opencode
    PR-URL: https://github.com/nodejs/node/pull/66132
    Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
    Reviewed-By: Matteo Collina <matteo.collina@gmail.com>

diff --git a/benchmark/common.js b/benchmark/common.js
index 8443da40d79..fa108b70683 100644
--- a/benchmark/common.js
+++ b/benchmark/common.js
@@ -198,6 +198,21 @@ class Benchmark {
   }

   _run() {
+    // A forked child is told to run the benchmark function directly, rather
+    // than build its own queue and fork again, through the
+    // NODE_RUN_BENCHMARK_FN environment variable. A child always inherits
+    // this.flags in its execArgv, so reaching _run() with those flags already
+    // applied means the variable did not survive to the child and every
+    // generation would keep forking. Fail loudly instead of forking forever.
+    if (process.send &&
+        this.flags.length > 0 &&
+        this.flags.every((flag) => process.execArgv.includes(flag))) {
+      throw new Error(
+        'Benchmark child process was started with the benchmark flags but ' +
+        'without NODE_RUN_BENCHMARK_FN, refusing to fork again. Something ' +
+        'removed the variable from the child environment.');
+    }
+
     // If forked, report to the parent.
     if (process.send) {
       process.send({
@@ -213,6 +228,20 @@ class Benchmark {
       this.originalOptions.setup(this.queue);
     }

+    // Enforcing the permission model removes the environment variables
+    // --allow-env does not grant access to at startup, which would drop the
+    // NODE_RUN_BENCHMARK_FN set below. The child only ever sees the
+    // environment this process hands it, so granting access to all of it does
+    // not widen what the benchmark can reach. Audit mode removes nothing, so
+    // it is left alone to keep its diagnostics intact.
+    const childExecArgv = this.flags.concat(process.execArgv);
+    const enforcesPermission = (arg) =>
+      arg === '--permission' || arg.startsWith('--permission=');
+    if (childExecArgv.some(enforcesPermission) &&
+        !childExecArgv.some((arg) => arg.startsWith('--allow-env'))) {
+      childExecArgv.push('--allow-env=*');
+    }
+
     const recursive = (queueIndex) => {
       const config = this.queue[queueIndex];

@@ -233,7 +262,7 @@ class Benchmark {

       const child = child_process.fork(require.main.filename, childArgs, {
         env: childEnv,
-        execArgv: this.flags.concat(process.execArgv),
+        execArgv: childExecArgv,
       });
       child.on('message', sendResult);
       child.on('close', (code) => {