Skip to content

Commit 83c41e4

Browse files
authored
fix(manifest): validate struct child lengths (#1054)
1 parent 0471f8f commit 83c41e4

1 file changed

Lines changed: 14 additions & 0 deletions

File tree

‎src/iceberg/manifest/manifest_reader.cc‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,16 @@ namespace {
5757
return InvalidArgument("Required field '{}' is null at row {}", field_name, row_idx);
5858
}
5959

60+
[[nodiscard]] Status ValidateStructLength(const ArrowArrayView* view,
61+
std::string_view field_name) {
62+
for (int64_t i = 0; i < view->n_children; ++i) {
63+
ICEBERG_CHECK(view->children[i]->length == view->length,
64+
"Field '{}' child {} should have length {} matching its parent, got {}",
65+
field_name, i, view->length, view->children[i]->length);
66+
}
67+
return {};
68+
}
69+
6070
[[nodiscard]] Status AssertViewType(const ArrowArrayView* view, ArrowType expected_type,
6171
std::string_view field_name) {
6272
if (view->storage_type != expected_type) {
@@ -318,6 +328,7 @@ Result<std::vector<ManifestFile>> ParseManifestList(ArrowSchema* arrow_schema,
318328

319329
ICEBERG_RETURN_UNEXPECTED(AssertViewTypeAndChildren(
320330
&view, ArrowType::NANOARROW_TYPE_STRUCT, schema.fields().size(), "manifest_list"));
331+
ICEBERG_RETURN_UNEXPECTED(ValidateStructLength(&view, "manifest_list"));
321332

322333
std::vector<ManifestFile> manifest_files;
323334
manifest_files.resize(array->length);
@@ -476,6 +487,7 @@ Status ParseDataFile(const std::shared_ptr<StructType>& data_file_schema,
476487
ICEBERG_RETURN_UNEXPECTED(
477488
AssertViewTypeAndChildren(view, ArrowType::NANOARROW_TYPE_STRUCT,
478489
data_file_schema->fields().size(), "data_file"));
490+
ICEBERG_RETURN_UNEXPECTED(ValidateStructLength(view, "data_file"));
479491

480492
for (int64_t col_idx = 0; col_idx < view->n_children; ++col_idx) {
481493
ICEBERG_ASSIGN_OR_RAISE(auto field, data_file_schema->GetFieldByIndex(col_idx));
@@ -515,6 +527,7 @@ Status ParseDataFile(const std::shared_ptr<StructType>& data_file_schema,
515527
case DataFile::kPartitionFieldId: {
516528
ICEBERG_RETURN_UNEXPECTED(
517529
AssertViewType(field_view, ArrowType::NANOARROW_TYPE_STRUCT, field_name));
530+
ICEBERG_RETURN_UNEXPECTED(ValidateStructLength(field_view, field_name));
518531
const auto& partition_type =
519532
internal::checked_cast<const StructType&>(*field->get().type());
520533
for (int64_t part_idx = 0; part_idx < field_view->n_children; part_idx++) {
@@ -647,6 +660,7 @@ Result<std::vector<ManifestEntry>> ParseManifestEntry(
647660

648661
ICEBERG_RETURN_UNEXPECTED(AssertViewTypeAndChildren(
649662
&view, ArrowType::NANOARROW_TYPE_STRUCT, schema.fields().size(), "manifest_entry"));
663+
ICEBERG_RETURN_UNEXPECTED(ValidateStructLength(&view, "manifest_entry"));
650664

651665
std::vector<ManifestEntry> manifest_entries;
652666
manifest_entries.resize(array->length);

0 commit comments

Comments
 (0)