summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzuisong <19145952+zuisong@users.noreply.github.com>2023-09-05 18:42:35 +0800
committerGitHub <noreply@github.com>2023-09-05 12:42:35 +0200
commit4a561f12dbae5a49203eb2c08fed71d9d0dfeb99 (patch)
tree15612ee40b52e5ddd24fdecdbf71d6747e8ea476
parent2a1ba2732e5cc04d74837dd9529dbab6e459117c (diff)
fix(node/child_process): don't crash on undefined/null value of an env var (#20378)
Fixes #20373 --------- Co-authored-by: Bartek IwaƄczuk <biwanczuk@gmail.com>
-rw-r--r--cli/tests/unit_node/child_process_test.ts57
-rw-r--r--ext/node/polyfills/internal/child_process.ts9
2 files changed, 64 insertions, 2 deletions
diff --git a/cli/tests/unit_node/child_process_test.ts b/cli/tests/unit_node/child_process_test.ts
index 9abd5c1e6..a282977e0 100644
--- a/cli/tests/unit_node/child_process_test.ts
+++ b/cli/tests/unit_node/child_process_test.ts
@@ -13,7 +13,7 @@ import {
import { Deferred, deferred } from "../../../test_util/std/async/deferred.ts";
import * as path from "../../../test_util/std/path/mod.ts";
-const { spawn, execFile, execFileSync, ChildProcess } = CP;
+const { spawn, spawnSync, execFile, execFileSync, ChildProcess } = CP;
function withTimeout<T>(timeoutInMS = 10_000): Deferred<T> {
const promise = deferred<T>();
@@ -640,3 +640,58 @@ Deno.test({
assertEquals(cp.signalCode, "SIGIOT");
},
});
+
+// Regression test for https://github.com/denoland/deno/issues/20373
+Deno.test(async function undefinedValueInEnvVar() {
+ const promise = withTimeout<string>();
+ const env = spawn(
+ `"${Deno.execPath()}" eval -p "Deno.env.toObject().BAZ"`,
+ {
+ env: {
+ BAZ: "BAZ",
+ NO_COLOR: "true",
+ UNDEFINED_ENV: undefined,
+ // deno-lint-ignore no-explicit-any
+ NULL_ENV: null as any,
+ },
+ shell: true,
+ },
+ );
+ try {
+ let envOutput = "";
+
+ assert(env.stdout);
+ env.on("error", (err: Error) => promise.reject(err));
+ env.stdout.on("data", (data) => {
+ envOutput += data;
+ });
+ env.on("close", () => {
+ promise.resolve(envOutput.trim());
+ });
+ await promise;
+ } finally {
+ env.kill();
+ }
+ const value = await promise;
+ assertEquals(value, "BAZ");
+});
+
+// Regression test for https://github.com/denoland/deno/issues/20373
+Deno.test(function spawnSyncUndefinedValueInEnvVar() {
+ const ret = spawnSync(
+ `"${Deno.execPath()}" eval -p "Deno.env.toObject().BAZ"`,
+ {
+ env: {
+ BAZ: "BAZ",
+ NO_COLOR: "true",
+ UNDEFINED_ENV: undefined,
+ // deno-lint-ignore no-explicit-any
+ NULL_ENV: null as any,
+ },
+ shell: true,
+ },
+ );
+
+ assertEquals(ret.status, 0);
+ assertEquals(ret.stdout.toString("utf-8").trim(), "BAZ");
+});
diff --git a/ext/node/polyfills/internal/child_process.ts b/ext/node/polyfills/internal/child_process.ts
index b11281fd7..33b0b3166 100644
--- a/ext/node/polyfills/internal/child_process.ts
+++ b/ext/node/polyfills/internal/child_process.ts
@@ -53,6 +53,13 @@ export function mapValues<T, O>(
const entries = Object.entries(record);
for (const [key, value] of entries) {
+ if (typeof value === "undefined") {
+ continue;
+ }
+ if (value === null) {
+ continue;
+ }
+
const mappedValue = transformer(value);
ret[key] = mappedValue;
@@ -836,7 +843,7 @@ export function spawnSync(
const output = new Deno.Command(command, {
args,
cwd,
- env,
+ env: mapValues(env, (value) => value.toString()),
stdout: toDenoStdio(normalizedStdio[1]),
stderr: toDenoStdio(normalizedStdio[2]),
uid,