Skip to content

Conversation

@KR-bluejay
Copy link
Contributor

Closes #610

Summary

  1. Cap sys_slice length at u32::MAX

    • Avoids IOCP truncation issues.
  2. Cap Write/WriteAt buffer lengths to u32::MAX

    • These are the only IOCP paths that touch the user buffer directly.
    • Other ops go through sys_slice and don’t need a separate clamp.
  3. Adjust read_len_over_u32 test

    • Updated to run on Windows in addition to existing platforms (io_uring).

Copy link
Member

@Berrysoft Berrysoft left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you also fix for Read & ReadAt?

@KR-bluejay
Copy link
Contributor Author

KR-bluejay commented Jan 5, 2026

Hi @Berrysoft ,
Is there a specific reason to do so, given that sys_slice_mut already handles it?

Regarding Read and ReadAt operations: they already invoke the sys_slice_mut function. Since the length is already capped to u32::MAX within the sys_slice implementation, I think additional clamping in these specific operations is unnecessary.

impl<T: IoBufMut, S: AsFd> OpCode for ReadAt<T, S> {
unsafe fn operate(self: Pin<&mut Self>, optr: *mut OVERLAPPED) -> Poll<io::Result<usize>> {
if let Some(overlapped) = unsafe { optr.as_mut() } {
overlapped.Anonymous.Anonymous.Offset = (self.offset & 0xFFFFFFFF) as _;
overlapped.Anonymous.Anonymous.OffsetHigh = (self.offset >> 32) as _;
}
let fd = self.fd.as_fd().as_raw_fd();
let slice = self.project().buffer.sys_slice_mut();
let mut transferred = 0;
let res = unsafe {
ReadFile(
fd,
slice.ptr() as _,
slice.len() as _,
&mut transferred,
optr,
)
};
win32_result(res, transferred)
}
fn cancel(self: Pin<&mut Self>, optr: *mut OVERLAPPED) -> io::Result<()> {
cancel(self.fd.as_fd().as_raw_fd(), optr)
}
}

impl<T: IoBufMut, S: AsFd> OpCode for Read<T, S> {
unsafe fn operate(self: Pin<&mut Self>, optr: *mut OVERLAPPED) -> Poll<io::Result<usize>> {
let fd = self.fd.as_fd().as_raw_fd();
let slice = self.project().buffer.sys_slice_mut();
let mut transferred = 0;
let res = unsafe {
ReadFile(
fd,
slice.ptr() as _,
slice.len() as _,
&mut transferred,
optr,
)
};
win32_result(res, transferred)
}
fn cancel(self: Pin<&mut Self>, optr: *mut OVERLAPPED) -> io::Result<()> {
cancel(self.fd.as_fd().as_raw_fd(), optr)
}
}

Copy link
Member

@Berrysoft Berrysoft left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough. LGTM.

@George-Miao George-Miao added bug Something isn't working driver: iocp About the IOCP driver package: driver Related to compio-driver labels Jan 5, 2026
@Berrysoft Berrysoft merged commit 7e33dc0 into compio-rs:master Jan 5, 2026
53 of 56 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working driver: iocp About the IOCP driver package: driver Related to compio-driver

Projects

None yet

Development

Successfully merging this pull request may close these issues.

IOCP: silent length truncation to u32 for buffers ≥ 4GB

3 participants