From cf6d0d8517d6ef86e2fc8235323e0e5166962352 Mon Sep 17 00:00:00 2001 From: Archkon <180910180+Archkon@users.noreply.github.com> Date: Tue, 28 Jul 2026 00:37:53 +0800 Subject: [PATCH] url: bounds-check short Windows file URL paths Check the decoded pathname length before reading the drive letter and colon. This prevents an out-of-bounds read for short URLs such as file:/// and reports ERR_INVALID_FILE_URL_PATH instead. Signed-off-by: Archkon <180910180+Archkon@users.noreply.github.com> --- src/node_url.cc | 6 ++++++ test/cctest/test_path.cc | 24 ++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/node_url.cc b/src/node_url.cc index 75aaf468f508f2..13e205640b6714 100644 --- a/src/node_url.cc +++ b/src/node_url.cc @@ -661,6 +661,12 @@ std::optional FileURLToPath(Environment* env, return "\\\\" + ada::idna::to_unicode(hostname) + decoded_pathname; } + if (decoded_pathname.size() < 3) { + THROW_ERR_INVALID_FILE_URL_PATH(env->isolate(), + "File URL path must be absolute"); + return std::nullopt; + } + char letter = decoded_pathname[1] | 0x20; char sep = decoded_pathname[2]; diff --git a/test/cctest/test_path.cc b/test/cctest/test_path.cc index 9e860d02cf77bd..1fd99134045243 100644 --- a/test/cctest/test_path.cc +++ b/test/cctest/test_path.cc @@ -8,6 +8,7 @@ #include "v8.h" using node::BufferValue; +using node::NormalizeFileURLOrPath; using node::PathResolve; using node::ToNamespacedPath; @@ -93,3 +94,26 @@ TEST_F(PathTest, ToNamespacedPath) { EXPECT_EQ(data.ToStringView(), "hello world"); // Input should not be mutated #endif } + +#ifdef _WIN32 +TEST_F(PathTest, NormalizeShortFileURLPath) { + const v8::HandleScope handle_scope(isolate_); + Argv argv; + Env env{handle_scope, argv, node::EnvironmentFlags::kNoBrowserGlobals}; + v8::TryCatch try_catch(isolate_); + + EXPECT_EQ(NormalizeFileURLOrPath(*env, "file:///"), ""); + ASSERT_TRUE(try_catch.HasCaught()); + + v8::Local exception = try_catch.Exception(); + ASSERT_TRUE(exception->IsObject()); + v8::Local code; + ASSERT_TRUE(exception.As() + ->Get((*env)->context(), + v8::String::NewFromUtf8Literal(isolate_, "code")) + .ToLocal(&code)); + ASSERT_TRUE(code->IsString()); + node::Utf8Value code_value(isolate_, code); + EXPECT_EQ(code_value.ToStringView(), "ERR_INVALID_FILE_URL_PATH"); +} +#endif