Skip to content

fix: seal FromBytes trait to prevent unsound external implementations (#10164)#10166

Open
sandy-sachin7 wants to merge 1 commit into
apache:mainfrom
sandy-sachin7:fix/seal-frombytes-trait
Open

fix: seal FromBytes trait to prevent unsound external implementations (#10164)#10166
sandy-sachin7 wants to merge 1 commit into
apache:mainfrom
sandy-sachin7:fix/seal-frombytes-trait

Conversation

@sandy-sachin7

Copy link
Copy Markdown

Which issue does this PR close?

Closes #10164.

Rationale for this change

FromBytes is a pub unsafe trait whose # Safety contract only documented bit-pattern validity. Internally, BitReader::get_batch fast-paths cast *mut T to *mut u16/u32/u64 and call std::slice::from_raw_parts_mut, which requires the pointer to be at least as aligned as the target primitive type. Because the documented contract did not mention alignment, a downstream crate could soundly implement FromBytes for a #[repr(packed)] type of size 2 (align 1) and trigger undefined behavior when passed to get_batch.

What changes are included in this PR?

  1. Sealed the trait: Added private::Sealed as a supertrait of FromBytes, preventing external implementations entirely — matching the existing pattern used by ParquetValueType in data_type.rs.

  2. Updated the # Safety contract: Now documents both the bit-pattern and alignment requirements.

  3. impl private::Sealed for every type implementing FromBytes: u8u64, i8i64, f32, f64, bool, Int96, ByteArray, FixedLenByteArray.

Are these changes tested?

All 22 existing bit_util tests pass. The change is purely structural — existing implementations are unaffected. External code that attempted to implement FromBytes (unlikely — none found in the wild) will get a compile error about the sealed supertrait, which is the desired outcome.

Are there any user-facing changes?

No API changes for existing users. External implementations of FromBytes or FromBitpacked are no longer possible (but were not intended to be extensible — the trait was only pub for visibility, not for extension).

…external implementations (apache#10164)

Seal the public unsafe trait `FromBytes` (and by extension `FromBitpacked`)
with a private supertrait so that it cannot be implemented outside the
`parquet` crate.

```rust
pub unsafe trait FromBytes: Sized + private::Sealed { ... }
```

This is necessary because `BitReader::get_batch` casts `*mut T` pointers to
`*mut u16`/u32/u64 and calls `std::slice::from_raw_parts_mut` on them,
which requires the pointer to be aligned for those primitive types.
The old `# Safety` contract only mentioned bit-pattern validity and did
not document the alignment requirement, so a downstream crate could
soundly implement `FromBytes` for a `#[repr(packed)]` type with size 2
but align 1 and trigger undefined behavior.

All in-crate implementations (`u8`-`u64`, `i8`-`i64`, `f32`, `f64`,
`bool`, `Int96`, `ByteArray`, `FixedLenByteArray`) already satisfy the
alignment requirement because they all have natural alignment matching
their size.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

parquet Changes to the parquet crate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Soundness: Unsound alignment contract in public FromBytes trait and BitReader::get_batch

1 participant