Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disallow null characters in URL <-> path conversions #33

Merged
merged 1 commit into from
Nov 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions include/upa/url.h
Original file line number Diff line number Diff line change
Expand Up @@ -3090,6 +3090,10 @@ inline url url_from_file_path(StrT&& str, file_path_format format = file_path_fo
}
}

// Check for null characters
if (util::contains_null(pointer, last))
throw url_error(validation_errc::null_character, "Path contains null character");

// make URL
detail::append_utf8_percent_encoded(pointer, last, *no_encode_set, str_url);
return url(str_url);
Expand Down Expand Up @@ -3164,6 +3168,11 @@ inline std::string path_from_file_url(const url& file_url, file_path_format form
}
}
}

// Check for null characters
if (util::contains_null(path.begin(), path.end()))
throw url_error(validation_errc::null_character, "Path contains null character");

return path;
}

Expand Down
1 change: 1 addition & 0 deletions include/upa/url_result.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ enum class validation_errc {
file_url_unsupported_host, ///< UNC path cannot have "." hostname
file_url_invalid_unc, ///< Invalid UNC path in file URL
file_url_not_windows_path, ///< Not a Windows path in file URL
null_character, ///< Path contains null character
};

/// @brief Check validation error code indicates success
Expand Down
5 changes: 5 additions & 0 deletions include/upa/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,11 @@ inline void append_ascii_lowercase(std::string& dest, const CharT* first, const

// Finders

template <class InputIt>
inline bool contains_null(InputIt first, InputIt last) {
return std::find(first, last, '\0') != last;
}

template <class CharT>
UPA_CONSTEXPR_17 bool has_xn_label(const CharT* first, const CharT* last) {
if (last - first >= 4) {
Expand Down
8 changes: 8 additions & 0 deletions test/test-url.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,8 @@ TEST_CASE("url_from_file_path") {
// non absolute path
CHECK_THROWS_AS(upa::url_from_file_path("path"), upa::url_error);
CHECK_THROWS_AS(upa::url_from_file_path("\\\\h\\p", upa::file_path_format::posix), upa::url_error);
// null character
CHECK_THROWS_AS(upa::url_from_file_path(std::string{ "/p\0", 3 }, upa::file_path_format::posix), upa::url_error);
}
SUBCASE("Windows path") {
// https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file
Expand Down Expand Up @@ -644,6 +646,8 @@ TEST_CASE("url_from_file_path") {
// unsupported pathes
CHECK_THROWS_AS(upa::url_from_file_path("\\\\?\\Volume{b75e2c83-0000-0000-0000-602f00000000}\\Test\\Foo.txt"), upa::url_error);
CHECK_THROWS_AS(upa::url_from_file_path("\\\\.\\Volume{b75e2c83-0000-0000-0000-602f00000000}\\Test\\Foo.txt"), upa::url_error);
// null character
CHECK_THROWS_AS(upa::url_from_file_path(std::string{ "/C:/p\0", 6 }, upa::file_path_format::posix), upa::url_error);
}
}

Expand All @@ -660,6 +664,8 @@ TEST_CASE("path_from_file_url") {
CHECK(path_from_file_url("file:///path", upa::file_path_format::posix) == "/path");
// POSIX path cannot have host
CHECK_THROWS_AS(path_from_file_url("file://host/path", upa::file_path_format::posix), upa::url_error);
// null character
CHECK_THROWS_AS(path_from_file_url("file:///p%00", upa::file_path_format::posix), upa::url_error);
}
SUBCASE("Windows path") {
CHECK(path_from_file_url("file:///C:", upa::file_path_format::windows) == "C:\\");
Expand All @@ -685,6 +691,8 @@ TEST_CASE("path_from_file_url") {
CHECK_THROWS_AS(path_from_file_url("file://///host/", upa::file_path_format::windows), upa::url_error);
// Unsupported "." hostname
CHECK_THROWS_AS(path_from_file_url("file://./name", upa::file_path_format::windows), upa::url_error);
// null character
CHECK_THROWS_AS(path_from_file_url("file:///C:/p%00", upa::file_path_format::posix), upa::url_error);
}
SUBCASE("Native path") {
#ifdef _WIN32
Expand Down
Loading