github-actions[bot] commented on code in PR #69527:
URL: https://github.com/apache/doris/pull/69527#discussion_r4361485535
##########
fe/fe-core/src/main/java/org/apache/doris/tablefunction/S3TableValuedFunction.java:
##########
@@ -89,6 +106,32 @@ public S3TableValuedFunction(Map<String, String>
properties, List<TBrokerFileSta
}
+ private static boolean isRemoteLanceUri(String path) {
+ try {
+ URI uri = new URI(path == null ? "" : path);
+ String scheme = uri.getScheme();
+ String authority = uri.getRawAuthority();
+ if (scheme == null ||
!LANCE_REMOTE_SCHEMES.contains(scheme.toLowerCase(Locale.ROOT))
+ || uri.isOpaque()) {
+ return false;
+ }
+ if (authority == null || authority.isEmpty()) {
+ // GooseFS can resolve its remote master from storage options
or configuration.
+ return "goosefs".equalsIgnoreCase(scheme) && uri.getRawPath()
!= null
+ && uri.getRawPath().startsWith("/");
+ }
+ // Lance falls back to a local path if Rust's URL parser rejects
the URI. Java's URI
+ // accepts registry authorities with invalid ports, which Rust
rejects. Validate the
+ // host/port separately without disallowing legitimate bucket
names with underscores.
+ String host =
HostAndPort.fromString(authority.substring(authority.lastIndexOf('@') + 1))
+ .requireBracketsForIPv6().getHost();
+ // Java accepts IPv6 zone identifiers, while Rust's URL parser
rejects them.
+ return !host.isEmpty() && !(host.contains(":") &&
host.contains("%"));
Review Comment:
[P1] Reject authorities that make Lance fall back to local paths
`S3("format"="lance", "fs.broker.support"="true",
"uri"="s3://bucket:-0/../../dataset.lance")` passes this check: Java URI
accepts the registry authority, and [HostAndPort parses `-0` as integer
zero](https://github.com/google/guava/blob/v33.2.1/guava/src/com/google/common/net/HostAndPort.java#L156-L192).
The pinned Rust URL parser [rejects the minus
sign](https://github.com/servo/rust-url/blob/v2.5.8/url/src/parser.rs#L1067-L1099),
so Lance [converts the parse failure into a local
path](https://github.com/lance-format/lance/blob/v12.0.0/rust/lance-io/src/object_store.rs#L483-L529).
`PathAbs` removes the two parent components, selecting `<process
cwd>/dataset.lance` without requiring either fake directory to exist. For an
existing dataset there, an ordinary user can open FE-local metadata while
`enable_local_tvf=false`; if the target also exists on the selected BE, its
`FILE_S3` range skips secure-root validation and reads locally too.
`s3://[::ffff:127.0.0.01]/../../dataset.lance
` is another accepted authority that Rust rejects because of its leading-zero
IPv4 tail. Validate the complete authority with SDK-compatible rules, or
prohibit downstream local fallback for remote TVFs, and cover both cases before
metadata loading.
##########
be/src/format_v2/table/lance_reader.cpp:
##########
@@ -35,11 +35,36 @@
#include "format_v2/lance/lance_reader_helper.h"
#include "format_v2/lance/lance_runtime_filter_helper.h"
#include "format_v2/lance/lance_session_manager.h"
+#include "io/fs/local_file_system.h"
#include "runtime/file_scan_profile.h"
#include "runtime/runtime_state.h"
namespace doris::format::lance {
+namespace {
+Status resolve_dataset_uri(const TFileRangeDesc& range, const
TFileScanRangeParams& scan_params,
+ std::string* uri) {
+ const auto& requested_uri =
range.table_format_params.lance_params.dataset_uri;
+ // Modern plans tag each range; older plans put the type in the scan
parameters.
+ // Untagged catalog scans retain their original storage-provider selection.
+ const bool is_local = range.__isset.file_type
+ ? range.file_type == TFileType::FILE_LOCAL
+ : scan_params.__isset.file_type &&
+ scan_params.file_type ==
TFileType::FILE_LOCAL;
+ // LOCAL TVF uses version zero for both schema discovery and whole-dataset
scans.
+ // Catalog scans pin a positive snapshot version, including file://
catalogs whose
+ // operator-configured warehouse is independent of the LOCAL TVF secure
directory.
+ if (is_local && range.table_format_params.lance_params.version == 0) {
+ // LOCAL Lance bypasses glob because it opens a dataset directory.
Apply the same
+ // canonical secure-root check before either schema discovery or a
cached dataset open.
+ return io::global_local_filesystem()->canonicalize_local_file(
Review Comment:
[P2] Decode file URIs before validating LOCAL Lance paths
With `user_files_secure_path=/srv/user_files`, an enabled, authorized LOCAL
Lance call using `file_path=file:///srv/user_files/a%20b.lance` should open the
in-root dataset `/srv/user_files/a b.lance`. The new resolver calls
`convert_to_abs_path`, which strips the scheme/authority but leaves `%20`
literal, so canonicalization now rejects this valid dataset (or selects the
wrong one if a literal `a%20b.lance` also exists). Previously the URI reached
Lance directly, whose pinned [FileStoreProvider decodes it with
`Url::to_file_path`](https://github.com/lance-format/lance/blob/68c12dfd7efe02f90ad2d7f3a239a7eb64884e57/rust/lance-io/src/object_store/providers/local.rs#L135-L147).
Decode actual file URIs before the canonical containment check while
preserving literal percent characters in bare paths, and add an escaped-URI
positive 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]