From 0e4e3277a9a6afb7665c2fc3d69343de587f1de0 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Sat, 13 Jun 2026 13:33:22 +0200 Subject: [PATCH] block: Add WriteZeroes sector overflow regression test Cover the prior commit by constructing a Request directly and a stub AsyncIo whose backend methods are unreachable, then submit a payload with sector + num_sectors past u64::MAX and assert BadRequest. Assisted-by: Claude:Opus-4.7 Signed-off-by: Anatol Belski --- block/src/io/request.rs | 59 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/block/src/io/request.rs b/block/src/io/request.rs index 74e3ba574..e6f8aeb07 100644 --- a/block/src/io/request.rs +++ b/block/src/io/request.rs @@ -651,3 +651,62 @@ impl Request { Ok(()) } } + +#[cfg(test)] +mod unit_tests { + use std::sync::Arc; + + use vm_memory::{Bytes as _, GuestMemoryMmap}; + use vmm_sys_util::eventfd::EventFd; + + use super::*; + use crate::async_io::{AsyncIo, AsyncIoCompletion, AsyncIoOperation, AsyncIoResult}; + + struct PanicAsyncIo(EventFd); + + impl AsyncIo for PanicAsyncIo { + fn notifier(&self) -> &EventFd { + &self.0 + } + fn submit_data_operation(&mut self, _: AsyncIoOperation) -> AsyncIoResult<()> { + unreachable!() + } + fn fsync(&mut self, _: Option) -> AsyncIoResult<()> { + unreachable!() + } + fn punch_hole(&mut self, _: u64, _: u64, _: u64) -> AsyncIoResult<()> { + unreachable!() + } + fn write_zeroes(&mut self, _: u64, _: u64, _: u64) -> AsyncIoResult<()> { + unreachable!() + } + fn next_completed_request(&mut self) -> Option { + None + } + } + + #[test] + fn write_zeroes_rejects_sector_arithmetic_overflow() { + let mem = Arc::new(GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 4096)]).unwrap()); + mem.write_slice(&(u64::MAX - 100).to_le_bytes(), GuestAddress(0)) + .unwrap(); + mem.write_slice(&1000u32.to_le_bytes(), GuestAddress(8)) + .unwrap(); + + let mut request = Request { + request_type: RequestType::WriteZeroes, + sector: 0, + data_descriptors: SmallVec::from_slice(&[(GuestAddress(0), DISCARD_WZ_SEG_SIZE)]), + status_addr: GuestAddress(0), + writeback: true, + start: Instant::now(), + }; + let mut disk = PanicAsyncIo(EventFd::new(0).unwrap()); + + let Err(ExecuteError::BadRequest(Error::InvalidOffset)) = + request.execute_async(mem, 1024, &mut disk, &[], false, 0) + else { + panic!("expected BadRequest(InvalidOffset)"); + }; + } +}