Skip to content
Open
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
13 changes: 10 additions & 3 deletions src/iceberg/table_metadata.cc
Original file line number Diff line number Diff line change
Expand Up @@ -517,11 +517,18 @@ int32_t TableMetadataUtil::ParseVersionFromLocation(std::string_view metadata_lo
size_t version_start = metadata_location.find_last_of('/') + 1;
size_t version_end = metadata_location.find('-', version_start);

if (version_end == std::string::npos) {
return -1;
}

int32_t version = -1;
if (version_end != std::string::npos) {
std::from_chars(metadata_location.data() + version_start,
metadata_location.data() + version_end, version);
const auto* version_begin = metadata_location.data() + version_start;
const auto* version_limit = metadata_location.data() + version_end;
const auto [ptr, ec] = std::from_chars(version_begin, version_limit, version);
if (ec != std::errc{} || ptr != version_limit) {
return -1;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a non blocking comment (especially given that this is a private method) but I wonder if we should change ParseVersionFromLocation() to return Result<> to ensure that callers explicit have to check for errors and act accordingly.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I considered that, but a parse failure is intentionally handled by starting at version 0, which matches the Java behavior. Returning the error from Write would change that fallback. Since this is a private helper with one caller and the -1 behavior is documented, I think keeping the sentinel is simpler here.

}

return version;
}

Expand Down
15 changes: 15 additions & 0 deletions src/iceberg/test/metadata_io_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,21 @@ TEST_F(MetadataIOTest, WriteMetadataWithBase) {
EXPECT_THAT(new_metadata_location, testing::HasSubstr("/metadata/00000-"));
}

{
// Reject malformed and out-of-range version segments.
for (const auto& base_metadata_location : {
"/metadata/00010x-xxx.metadata.json",
"/metadata/2147483648-xxx.metadata.json",
"/metadata/-xxx.metadata.json",
}) {
TableMetadata new_metadata = PrepareMetadata();
ICEBERG_UNWRAP_OR_FAIL(
auto new_metadata_location,
TableMetadataUtil::Write(*io_, &base, base_metadata_location, new_metadata));
EXPECT_THAT(new_metadata_location, testing::HasSubstr("/metadata/00000-"));
}
}

// Reset base metadata_file_location
// base.metadata_file_location = temp_filepath_;

Expand Down
Loading