0xMiden / 0xMiden/miden-signature

bug: `flatten_ef`/`unflatten_ef` use unsafe transmute with unverified memory layout assumption

未關閉
#1 1 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視
主要語言
Rust
星號
2
分支
1
PR 合併指標
30 天內沒有已合併 PR

描述

## Summary

`flatten_ef` and `unflatten_ef` in `src/internal/proof.rs` cast between `&[EF]` and `&[Goldilocks]` via raw pointer transmute, relying on the assumption that `BinomialExtensionField` has the same memory layout as `[Goldilocks; D]`. This assumption is not verified at compile time and is not guaranteed by Rust's type system.

## Code

```rust
fn flatten_ef>(ef_slice: &[EF]) -> &[Goldilocks] {
let len = ef_slice.len() * EF::DIMENSION;
// Safety: relies on BinomialExtensionField being layout-compatible with [Goldilocks; D]
unsafe { core::slice::from_raw_parts(ef_slice.as_ptr() as *const Goldilocks, len) }
}

fn unflatten_ef>(base_slice: &[Goldilocks]) -> &[EF] {
let len = base_slice.len() / EF::DIMENSION;
unsafe { core::slice::from_raw_parts(base_slice.as_ptr() as *const EF, len) }
}
```

## Why this is unsound

In Rust, `repr(transparent)` only applies to single-field newtype structs. A struct wrapping `[F; D]` can have additional padding or alignment requirements (e.g. from `PhantomData` fields) that differ from `[Goldilocks; D]`. Without a compile-time layout assertion, this is unsound undefined behavior if the layouts differ by even one byte.

These functions are called on every `sign` and `verify` invocation.

## Suggested fix

Use `bytemuck` with a compile-time `Pod` + `Zeroable` bound and a `cast_slice` call, which enforces layout compatibility at compile time:

```rust
fn flatten_ef>(ef_slice: &[EF]) -> &[Goldilocks] {
bytemuck::cast_slice(ef_slice)
}
```

Or add an explicit compile-time size assertion:

```rust
const _: () = assert!(
core::mem::size_of::>()
== core::mem::size_of::<[Goldilocks; 2]>()
);
```

貢獻指南

開啟貢獻指南

評估

這個 Issue 還沒有評估資料。

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。