github-actions[bot] commented on code in PR #69528:
URL: https://github.com/apache/doris/pull/69528#discussion_r4370544042
##########
be/src/io/fs/local_file_system.cpp:
##########
@@ -452,31 +452,206 @@ const std::shared_ptr<LocalFileSystem>&
global_local_filesystem() {
return local_fs;
}
+Status LocalFileSystem::parse_local_path(const std::string& file_path, Path&
local_path) {
+ // Reject embedded NULs before passing paths to filesystem APIs that use C
strings.
+ if (file_path.empty() || file_path.find('\0') != std::string::npos) {
+ return Status::InvalidArgument("local file path must not be empty or
contain NUL");
+ }
+ // Match URL preprocessing only for actual file URIs; bare paths keep
literal whitespace.
+ const auto is_c0_or_space = [](unsigned char c) { return c <= 0x20; };
+ size_t begin = 0;
+ size_t end = file_path.size();
+ while (begin < end && is_c0_or_space(file_path[begin])) {
+ ++begin;
+ }
+ while (end > begin && is_c0_or_space(file_path[end - 1])) {
+ --end;
+ }
+ std::string uri_input;
+ for (size_t i = begin; i < end; ++i) {
+ if (file_path[i] != '\t' && file_path[i] != '\r' && file_path[i] !=
'\n') {
+ uri_input += file_path[i];
+ }
+ }
+ const bool is_file_uri = uri_input.size() >= 5 &&
+ (uri_input[0] == 'f' || uri_input[0] == 'F') &&
+ (uri_input[1] == 'i' || uri_input[1] == 'I') &&
+ (uri_input[2] == 'l' || uri_input[2] == 'L') &&
+ (uri_input[3] == 'e' || uri_input[3] == 'E') &&
uri_input[4] == ':';
+ std::string local_input = is_file_uri ? std::move(uri_input) : file_path;
+ if (is_file_uri) {
+ local_input.replace(0, 4, "file");
+ // File URLs treat raw backslashes as separators, including before the
authority.
+ // Do this before conversion; percent-encoded backslashes must remain
literal.
+ for (size_t i = 5; i < local_input.size(); ++i) {
+ if (local_input[i] == '\\') {
+ local_input[i] = '/';
+ }
+ }
+ }
+ const auto hex_digit = [](char c) -> int {
+ if (c >= '0' && c <= '9') return c - '0';
+ if (c >= 'a' && c <= 'f') return c - 'a' + 10;
+ if (c >= 'A' && c <= 'F') return c - 'A' + 10;
+ return -1;
+ };
+ const auto percent_decode = [&](const std::string& encoded) {
+ std::string decoded;
+ decoded.reserve(encoded.size());
+ for (size_t i = 0; i < encoded.size(); ++i) {
+ if (encoded[i] == '%' && i + 2 < encoded.size()) {
+ const int high = hex_digit(encoded[i + 1]);
+ const int low = hex_digit(encoded[i + 2]);
+ if (high >= 0 && low >= 0) {
+ decoded += static_cast<char>((high << 4) | low);
+ i += 2;
+ continue;
+ }
+ }
+ decoded += encoded[i];
+ }
+ return decoded;
+ };
+ const auto is_drive = [](const std::string& segment) {
+ return segment.size() == 2 &&
+ ((segment[0] >= 'a' && segment[0] <= 'z') ||
+ (segment[0] >= 'A' && segment[0] <= 'Z')) &&
+ (segment[1] == ':' || segment[1] == '|');
+ };
+ bool empty_file_host = false;
+ if (is_file_uri && local_input.compare(5, 2, "//") == 0) {
+ const auto host_end = local_input.find_first_of("/?#", 7);
+ auto host = local_input.substr(7, host_end == std::string::npos ?
host_end : host_end - 7);
+ if (is_drive(host)) {
+ // The URL parser treats a drive in the host position as the first
path segment.
+ local_input.erase(5, 2);
+ } else {
+ host = percent_decode(host);
+ std::transform(host.begin(), host.end(), host.begin(), [](unsigned
char c) {
+ return c >= 'A' && c <= 'Z' ? c + ('a' - 'A') : c;
+ });
+ empty_file_host = host.empty() || host == "localhost";
+ }
+ }
+ // Convert file: URIs to filesystem paths and reject remote schemes before
any reader opens them.
+ RETURN_IF_ERROR(convert_to_abs_path(local_input, local_path));
Review Comment:
[P2] Preserve SDK fallback identity for malformed file authorities
With LOCAL enabled, an ADMIN/OPERATOR, and both BE cwd and
user_files_secure_path set to /secure, consider
file_path='file://host:80/secure/data.lance'. The [pinned URL parser rejects a
colon in a file
host](https://github.com/servo/rust-url/blob/v2.5.8/idna/src/uts46.rs#L343-L351),
so [Lance falls back to treating the entire original string as a cwd-relative
filesystem
path](https://github.com/lance-format/lance/blob/68c12dfd7efe02f90ad2d7f3a239a7eb64884e57/rust/lance-io/src/object_store.rs#L528-L545):
/secure/file:/host:80/secure/data.lance. This call instead strips host:80
without validating it and resolves /secure/data.lance; resolve_dataset_uri sees
success and skips the SDK parser. If those two in-root datasets contain
different rows, schema discovery and scanning now silently select the other
dataset. Preserve the SDK's parse/fallback identity before containment, or
reject the malformed authority instead of rewriting it, and add a
distinguishable-dataset collision case.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]