From 88dc94bd40957dc26e2bd6858eef2de14ea8f0c0 Mon Sep 17 00:00:00 2001 From: abdul rawoof Date: Wed, 26 Aug 2026 14:54:14 +0530 Subject: [PATCH] GH-51005: [C++] fix over-read in UriFromAbsolutePath posix branch the posix branch of UriFromAbsolutePath hands path.data() from a std::string_view straight to uriUnixFilenameToUriStringA, which scans its argument as a nul-terminated c string. a view is not required to be nul-terminated, so one backed by a larger buffer makes the routine read past the view, and because out was sized from path.length() a longer run also writes past out. the windows branch above already sidesteps this by copying into a std::string first, so do the same on posix and pass the terminated buffer. --- cpp/src/arrow/util/uri.cc | 9 +++++++-- cpp/src/arrow/util/uri_test.cc | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/cpp/src/arrow/util/uri.cc b/cpp/src/arrow/util/uri.cc index 6c0787a87e04..25af8a74c385 100644 --- a/cpp/src/arrow/util/uri.cc +++ b/cpp/src/arrow/util/uri.cc @@ -338,8 +338,13 @@ Result UriFromAbsolutePath(std::string_view path) { // uriWindowsFilenameToUriStringA basically only fails if a null pointer is given. ARROW_CHECK_EQ(r, 0) << "uriWindowsFilenameToUriStringA unexpectedly failed"; #else - out.resize(7 + 3 * path.length() + 1); - int r = uriUnixFilenameToUriStringA(path.data(), out.data()); + // uriUnixFilenameToUriStringA scans its argument as a NUL-terminated C string, + // but a std::string_view is not required to be NUL-terminated. Copy into a + // std::string first (as the Windows branch above already does) so the routine + // cannot read past the end of the view. + std::string fixed_path(path); + out.resize(7 + 3 * fixed_path.length() + 1); + int r = uriUnixFilenameToUriStringA(fixed_path.data(), out.data()); // same as above (uriWindowsFilenameToUriStringA) ARROW_CHECK_EQ(r, 0) << "uriUnixFilenameToUriStringA unexpectedly failed"; #endif diff --git a/cpp/src/arrow/util/uri_test.cc b/cpp/src/arrow/util/uri_test.cc index 36e09b1b2e87..8c9f932f54e8 100644 --- a/cpp/src/arrow/util/uri_test.cc +++ b/cpp/src/arrow/util/uri_test.cc @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -370,4 +371,19 @@ TEST(UriFromAbsolutePath, Basics) { #endif } +TEST(UriFromAbsolutePath, NonNulTerminatedView) { + // The argument is a std::string_view, which is not required to be + // NUL-terminated. A view backed by a larger buffer must not make the + // conversion consume bytes beyond the view's length. +#ifdef _WIN32 + std::string backing = "C:/foo/bar and more bytes"; + std::string_view path(backing.data(), std::string_view("C:/foo/bar").size()); + ASSERT_OK_AND_EQ("file:///C:/foo/bar", UriFromAbsolutePath(path)); +#else + std::string backing = "/tmp/foo and more bytes"; + std::string_view path(backing.data(), std::string_view("/tmp/foo").size()); + ASSERT_OK_AND_EQ("file:///tmp/foo", UriFromAbsolutePath(path)); +#endif +} + } // namespace arrow::util