//! No field of a source sizes an allocation: a WAV `data` chunk that declares 4 GiB, and //! a Y4M header that declares a 4096 × 4096 frame, each followed by a few bytes, are //! refused having allocated about what they held. Its own binary: it installs a //! counting global allocator. use std::alloc::{GlobalAlloc, Layout, System}; use std::sync::atomic::{AtomicUsize, Ordering}; struct Peak; static LIVE: AtomicUsize = AtomicUsize::new(0); static PEAK: AtomicUsize = AtomicUsize::new(0); unsafe impl GlobalAlloc for Peak { unsafe fn alloc(&self, l: Layout) -> *mut u8 { let p = unsafe { System.alloc(l) }; if !p.is_null() { let now = LIVE.fetch_add(l.size(), Ordering::SeqCst) + l.size(); PEAK.fetch_max(now, Ordering::SeqCst); } p } unsafe fn dealloc(&self, p: *mut u8, l: Layout) { unsafe { System.dealloc(p, l) }; LIVE.fetch_sub(l.size(), Ordering::SeqCst); } } #[global_allocator] static A: Peak = Peak; /// The most a reader may hold beyond what it was handed, for files of a few bytes. const BOUND: usize = 1 << 20; fn peak_of(f: impl FnOnce() -> &'static str) -> (&'static str, usize) { let base = LIVE.load(Ordering::SeqCst); PEAK.store(base, Ordering::SeqCst); let v = f(); (v, PEAK.load(Ordering::SeqCst) - base) } #[test] fn a_declared_size_never_sizes_a_buffer() { let mut wav = b"RIFF\0\0\0\0WAVEfmt \x10\0\0\0".to_vec(); wav.extend_from_slice(&[1, 0, 1, 0]); // PCM, one channel wav.extend_from_slice(&8000u32.to_le_bytes()); wav.extend_from_slice(&16000u32.to_le_bytes()); wav.extend_from_slice(&[2, 0, 16, 0]); // align 2, 16 bits wav.extend_from_slice(b"data"); wav.extend_from_slice(&0xffff_fffeu32.to_le_bytes()); wav.extend_from_slice(&[0; 4]); let (v, peak) = peak_of(|| wai_pack::conformance::source_verdict("x.wav", &wav)); assert_eq!(v, "wav-truncated"); assert!(peak < BOUND, "a 4 GiB data claim allocated {peak} bytes"); // The reader's own bound, whatever block a caller asks for. let (v, peak) = peak_of(|| { let mut r = wai_pack::source::wav::WavReader::new(&wav[..]).unwrap(); r.next_block(u64::MAX).map(|_| "ok").unwrap_or_else(|e| e.code()) }); assert_eq!(v, "wav-truncated"); assert!(peak < BOUND, "next_block(u64::MAX) on a 4 GiB data claim allocated {peak} bytes"); let y4m = [&b"YUV4MPEG2 W4096 H4096 F25:1 C444\nFRAME\n"[..], &[16; 6]].concat(); let (v, peak) = peak_of(|| wai_pack::conformance::source_verdict("x.y4m", &y4m)); assert_eq!(v, "y4m-truncated"); assert!(peak < BOUND, "a 4096 × 4096 frame header allocated {peak} bytes"); }