1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-28 16:20:57 -05:00

fix(node/fs): add missing stat path argument validation (#27086)

We didn't validate the `path` argument that's passed to `fs.stat()` and
`fs.statSync()` which lead to wrong errors being thrown. The
`@rollup/plugin-node-resolve` code calls it with `undefined` quite a lot
which lead to `nitro` and `nuxt` failing.

Fixes https://github.com/denoland/deno/issues/26700

---------

Co-authored-by: Yoshiya Hinosawa <stibium121@gmail.com>
This commit is contained in:
Marvin Hagemeister 2024-11-27 08:35:39 +01:00 committed by GitHub
parent 42b71d82db
commit 927352bd4e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 44 additions and 2 deletions

View file

@ -6,6 +6,7 @@
import { denoErrorToNodeError } from "ext:deno_node/internal/errors.ts";
import { promisify } from "ext:deno_node/internal/util.mjs";
import { primordials } from "ext:core/mod.js";
import { getValidatedPath } from "ext:deno_node/internal/fs/utils.mjs";
const { ObjectCreate, ObjectAssign } = primordials;
@ -379,6 +380,7 @@ export function stat(
? optionsOrCallback
: { bigint: false };
path = getValidatedPath(path).toString();
if (!callback) throw new Error("No callback function supplied");
Deno.stat(path).then(
@ -409,6 +411,8 @@ export function statSync(
path: string | URL,
options: statOptions = { bigint: false, throwIfNoEntry: true },
): Stats | BigIntStats | undefined {
path = getValidatedPath(path).toString();
try {
const origin = Deno.statSync(path);
return CFISBIS(origin, options.bigint);

View file

@ -1,7 +1,7 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
import { assertCallbackErrorUncaught } from "../_test_utils.ts";
import { BigIntStats, stat, Stats, statSync } from "node:fs";
import { assertEquals, fail } from "@std/assert";
import { assert, assertEquals, fail } from "@std/assert";
export function assertStats(actual: Stats, expected: Deno.FileInfo) {
assertEquals(actual.dev, expected.dev);
@ -152,3 +152,38 @@ Deno.test({
assertEquals(stats.isSocket(), false);
},
});
Deno.test({
name: "[node/fs] stat invalid path error",
async fn() {
try {
await new Promise<Stats>((resolve, reject) => {
stat(
// deno-lint-ignore no-explicit-any
undefined as any,
(err, stats) => err ? reject(err) : resolve(stats),
);
});
fail();
} catch (err) {
assert(err instanceof TypeError);
// deno-lint-ignore no-explicit-any
assertEquals((err as any).code, "ERR_INVALID_ARG_TYPE");
}
},
});
Deno.test({
name: "[node/fs] statSync invalid path error",
fn() {
try {
// deno-lint-ignore no-explicit-any
statSync(undefined as any);
fail();
} catch (err) {
assert(err instanceof TypeError);
// deno-lint-ignore no-explicit-any
assertEquals((err as any).code, "ERR_INVALID_ARG_TYPE");
}
},
});

View file

@ -3,6 +3,7 @@
/// <reference lib="deno.ns" />
import { assert, assertEquals, assertRejects, assertThrows } from "@std/assert";
import { join } from "node:path";
import { fileURLToPath } from "node:url";
import { tmpdir } from "node:os";
import {
closeSync,
@ -160,7 +161,9 @@ Deno.test(
} catch (error: unknown) {
assertEquals(
`${error}`,
`Error: ENOENT: no such file or directory, stat '${fileUrl.pathname}'`,
`Error: ENOENT: no such file or directory, stat '${
fileURLToPath(fileUrl)
}'`,
);
}
},