Skip to content

fix(table): reject invalid global index metadata#578

Open
XiaoHongbo-Hope wants to merge 5 commits into
apache:mainfrom
XiaoHongbo-Hope:fix_global_index_missing_meta
Open

fix(table): reject invalid global index metadata#578
XiaoHongbo-Hope wants to merge 5 commits into
apache:mainfrom
XiaoHongbo-Hope:fix_global_index_missing_meta

Conversation

@XiaoHongbo-Hope

@XiaoHongbo-Hope XiaoHongbo-Hope commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #577.

Missing or malformed metadata for a declared sorted global-index entry could previously be converted into an empty BTreeIndexMeta. That metadata is interpreted as an only-null index, so file pruning could silently omit matching rows. Malformed key lengths could also panic during deserialization, and a truncated null-flags trailer could be interpreted as legacy metadata.

Because the manifest already declares these entries as BTree or Bitmap indexes, missing or corrupt metadata is invalid table data. This change surfaces DataInvalid instead of silently falling back to a normal scan.

Changes

  • Change GlobalIndexScanner::create to return Result<Option<Self>>, reserving Ok(None) for cases with no applicable sorted index.
  • Reject missing outer metadata, missing serialized index metadata, and deserialization failures for declared BTree/Bitmap entries; preserve the underlying parse error as the source.
  • Validate serialized first-key and last-key lengths before slicing, returning InvalidData for negative or truncated lengths.
  • Reject a one-byte, truncated versioned null-flags trailer instead of treating it as legacy metadata.
  • Add regressions for all three scanner metadata errors, invalid key lengths, and truncated trailers.

Testing

  • cargo fmt --all -- --check
  • cargo clippy -p paimon --all-targets -- -D warnings
  • cargo test -p paimon global_index_scanner (37 passed)
  • cargo test -p paimon btree::meta (6 passed)
  • cargo test -p paimon --all-targets (1727 passed, 1 ignored)

Notes

There is no public API or storage-format change. Valid legacy and versioned BTree metadata remain supported.

Preserve unavailable sorted-index metadata instead of treating it as an only-null index. Validate serialized key lengths so malformed metadata returns an error and the scanner can fall back safely.
Fall back when a sorted index entry lacks its outer metadata, and reject truncated versioned BTree metadata trailers.

@JingsongLi JingsongLi left a comment

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.

Blocking: malformed global-index metadata is currently treated as an unavailable optimization and silently falls back to a normal table scan.

BTreeIndexMeta::deserialize(bytes).ok() discards the InvalidData error, and evaluate_leaf later returns Ok(None) when any shard has unavailable metadata. This makes a corrupted or incomplete declared BTree/Bitmap index indistinguishable from an unsupported predicate or an absent index. It also hides storage corruption and may unexpectedly turn an indexed query into a full scan without any warning.

The bounds checks added to BTreeIndexMeta::deserialize are correct: malformed external data must return a structured error instead of panicking. However, that error should be propagated as Error::DataInvalid, consistent with failures while opening or querying the physical index file.

Please consider changing GlobalIndexScanner::create to return Result<Option<Self>>, reserving Ok(None) for cases where no applicable index exists or the predicate cannot be evaluated. Missing required metadata and deserialization failures for a declared sorted index should return Err. The regression tests should assert an error rather than a successful fallback.

@XiaoHongbo-Hope XiaoHongbo-Hope changed the title fix(table): fall back on invalid global index metadata fix(table): reject invalid global index metadata Jul 22, 2026
@XiaoHongbo-Hope

Copy link
Copy Markdown
Contributor Author

Blocking: malformed global-index metadata is currently treated as an unavailable optimization and silently falls back to a normal table scan.

BTreeIndexMeta::deserialize(bytes).ok() discards the InvalidData error, and evaluate_leaf later returns Ok(None) when any shard has unavailable metadata. This makes a corrupted or incomplete declared BTree/Bitmap index indistinguishable from an unsupported predicate or an absent index. It also hides storage corruption and may unexpectedly turn an indexed query into a full scan without any warning.

The bounds checks added to BTreeIndexMeta::deserialize are correct: malformed external data must return a structured error instead of panicking. However, that error should be propagated as Error::DataInvalid, consistent with failures while opening or querying the physical index file.

Please consider changing GlobalIndexScanner::create to return Result<Option<Self>>, reserving Ok(None) for cases where no applicable index exists or the predicate cannot be evaluated. Missing required metadata and deserialization failures for a declared sorted index should return Err. The regression tests should assert an error rather than a successful fallback.

Fixed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Missing global index metadata can silently prune matching rows

2 participants