refactor(pf-bitstream): the parser layer is now compiler-enforced unsafe-free
#![forbid(unsafe_code)] on both crates. Upstream's codec module was one production unsafe away: build_ref_pic_lists turned DPB borrows into indices via pointer offset_from — same pointer-identity mapping now expressed as position(ptr::eq) over the <=16-entry DPB (PROVENANCE #5). Three test-only mem::zeroed() asserts became Default::default(), an identical value for the all-integer PredWeightTable. Honest coverage note: build_ref_pic_lists has no callers inside the vendored subset (its consumer was the non-vendored stateless layer), so the rewrite is equivalence-by-construction until the DecodePlan layer exercises it against goldens.
This commit is contained in:
@@ -15,7 +15,10 @@
|
||||
//! where cheap; reject-with-log outside that envelope rather than half-decode.
|
||||
//!
|
||||
//! Nothing in this crate may touch a GPU API, an OS handle, or the network: CPU-only by
|
||||
//! construction, so its tests run on every CI leg including macOS.
|
||||
//! construction, so its tests run on every CI leg including macOS. And no `unsafe`,
|
||||
//! compiler-enforced — this layer exists to replace C parsers; it does not get to
|
||||
//! reintroduce their failure mode.
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
// The vendor-pinning smoke tests below assert against byte counts and golden values from
|
||||
// the vendored snapshot's own test vectors; a cros-codecs re-sync that shifts parser
|
||||
|
||||
@@ -40,6 +40,13 @@ in the future."
|
||||
3. `Cargo.toml` — rewritten: `log` is the only dependency the vendored subset needs,
|
||||
plus `env_logger`/`serde_json` dev-dependencies for upstream's in-tree tests.
|
||||
4. `cargo fmt` normalization under the workspace's rustfmt config (mechanical only).
|
||||
5. **Zero-unsafe, enforced**: `#![forbid(unsafe_code)]` added to lib.rs. Upstream's codec
|
||||
module had exactly one production `unsafe` (h264/dpb.rs `build_ref_pic_lists`: ref→index
|
||||
via pointer `offset_from`) — replaced with a safe `position(ptr::eq)` over the ≤16-entry
|
||||
DPB — and three test-only `mem::zeroed()` asserts, replaced with `Default::default()`
|
||||
(`PredWeightTable` derives `Default`; all-integer struct, identical value). The layer
|
||||
facing untrusted bytes is now compiler-verified free of unsafe — the property that
|
||||
motivates replacing libavcodec's C parsers in the first place.
|
||||
|
||||
Re-sync procedure: fetch the AOSP tree, re-apply this trim, diff `codec/` +
|
||||
`bitstream_utils.rs` (expect near-zero conflicts), update the commit pin above.
|
||||
|
||||
@@ -1255,12 +1255,18 @@ impl<T: Clone> Dpb<T> {
|
||||
)
|
||||
};
|
||||
|
||||
let dpb_start = self.entries.as_ptr();
|
||||
let refs_to_index = |refs: Vec<_>| {
|
||||
// punktfunk deviation (PROVENANCE.md #5): upstream computed these indices with an
|
||||
// unsafe `offset_from` against the entries base pointer. Same pointer-identity
|
||||
// mapping, expressed safely — the DPB holds at most 16 entries, so the linear
|
||||
// `position` is noise, and the crate stays `#![forbid(unsafe_code)]`.
|
||||
let refs_to_index = |refs: Vec<&DpbEntry<T>>| {
|
||||
refs.into_iter()
|
||||
.map(|r| r as *const DpbEntry<T>)
|
||||
.map(|r| unsafe { r.offset_from(dpb_start) })
|
||||
.map(|i| i as usize)
|
||||
.map(|r| {
|
||||
self.entries
|
||||
.iter()
|
||||
.position(|e| std::ptr::eq(e, r))
|
||||
.expect("every reference list entry comes from this DPB")
|
||||
})
|
||||
.collect()
|
||||
};
|
||||
|
||||
|
||||
@@ -2883,7 +2883,7 @@ mod tests {
|
||||
}
|
||||
|
||||
// Safe because this type does not have any references
|
||||
assert_eq!(hdr.pred_weight_table, unsafe { std::mem::zeroed() });
|
||||
assert_eq!(hdr.pred_weight_table, Default::default());
|
||||
|
||||
assert_eq!(hdr.dec_ref_pic_marking, Default::default());
|
||||
|
||||
@@ -2939,7 +2939,7 @@ mod tests {
|
||||
}
|
||||
|
||||
// Safe because this type does not have any references
|
||||
assert_eq!(hdr.pred_weight_table, unsafe { std::mem::zeroed() });
|
||||
assert_eq!(hdr.pred_weight_table, Default::default());
|
||||
|
||||
assert_eq!(hdr.dec_ref_pic_marking, Default::default());
|
||||
|
||||
@@ -2995,7 +2995,7 @@ mod tests {
|
||||
}
|
||||
|
||||
// Safe because this type does not have any references
|
||||
assert_eq!(hdr.pred_weight_table, unsafe { std::mem::zeroed() });
|
||||
assert_eq!(hdr.pred_weight_table, Default::default());
|
||||
|
||||
assert_eq!(hdr.dec_ref_pic_marking, Default::default());
|
||||
|
||||
|
||||
@@ -18,6 +18,11 @@
|
||||
// Held-back lints here, PROVENANCE.md records the posture.
|
||||
#![allow(clippy::all)]
|
||||
#![allow(mismatched_lifetime_syntaxes)]
|
||||
// The one bar vendored code IS held to, and the whole point of this layer: the code that
|
||||
// parses hostile bitstream bytes contains no unsafe, compiler-enforced. Upstream was one
|
||||
// pointer-subtraction away from this already (PROVENANCE.md #5); a re-sync that brings
|
||||
// unsafe into the codec module must fail here and be judged, not slide in.
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
pub mod bitstream_utils;
|
||||
pub mod codec;
|
||||
|
||||
Reference in New Issue
Block a user