Skip to content

Commit 74db854

Browse files
committed
fix impl_nio_read_iovec/impl_nio_write_iovec bug
1 parent b1a1896 commit 74db854

2 files changed

Lines changed: 27 additions & 14 deletions

File tree

core/src/syscall/unix/mod.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,9 @@ macro_rules! impl_nio_read_iovec {
566566
let mut received = 0usize;
567567
let mut r = -1;
568568
let mut index = 0;
569-
'outer: for iovec in &vec {
569+
for iovec in &vec {
570+
let stage = length;
571+
let mut offset = received.saturating_sub(stage);
570572
length += iovec.iov_len;
571573
if received > length {
572574
index += 1;
@@ -577,6 +579,13 @@ macro_rules! impl_nio_read_iovec {
577579
arg.push(*i);
578580
}
579581
while received < length && left_time > 0 {
582+
// Assuming iov_len is 4, but only 1 is read, at this point we should continue trying to fill the current iovec
583+
if 0 != offset {
584+
arg[0] = libc::iovec {
585+
iov_base: (arg[0].iov_base as usize + offset) as *mut std::ffi::c_void,
586+
iov_len: arg[0].iov_len - offset,
587+
};
588+
}
580589
r = self.inner.$syscall(
581590
fn_ptr,
582591
$fd,
@@ -596,9 +605,11 @@ macro_rules! impl_nio_read_iovec {
596605
} else if r != -1 {
597606
$crate::syscall::reset_errno();
598607
received += libc::size_t::try_from(r).expect("r overflow");
599-
r = received.try_into().expect("received overflow");
600-
// readv returns as soon as any data is received
601-
break 'outer;
608+
if received >= length {
609+
r = received.try_into().expect("received overflow");
610+
break;
611+
}
612+
offset = received.saturating_sub(stage);
602613
}
603614
let error_kind = std::io::Error::last_os_error().kind();
604615
if error_kind == std::io::ErrorKind::WouldBlock {

core/src/syscall/windows/mod.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -533,8 +533,9 @@ macro_rules! impl_nio_read_iovec {
533533
let mut received = 0usize;
534534
let mut r = windows_sys::Win32::Networking::WinSock::SOCKET_ERROR;
535535
let mut index = 0;
536-
'outer: for iovec in &vec {
537-
let mut offset = received.saturating_sub(length);
536+
for iovec in &vec {
537+
let stage = length;
538+
let mut offset = received.saturating_sub(stage);
538539
length += iovec.len as usize;
539540
if received > length {
540541
index += 1;
@@ -545,6 +546,7 @@ macro_rules! impl_nio_read_iovec {
545546
arg.push(*i);
546547
}
547548
while received < length && left_time > 0 {
549+
// Assuming len is 4, but only 1 is read, at this point we should continue trying to fill the current WSABUF
548550
if 0 != offset {
549551
arg[0] = windows_sys::Win32::Networking::WinSock::WSABUF {
550552
buf: (arg[0].buf as usize + offset) as windows_sys::core::PSTR,
@@ -563,12 +565,13 @@ macro_rules! impl_nio_read_iovec {
563565
);
564566
if r != windows_sys::Win32::Networking::WinSock::SOCKET_ERROR {
565567
$crate::syscall::reset_errno();
566-
// WSARecv returns 0 on success; actual byte count is in *$recvd
567-
received += unsafe { *$recvd } as usize;
568-
r = 0;
569-
unsafe{ $recvd.write(received.try_into().expect("overflow")) };
570-
// WSARecv returns as soon as any data is received
571-
break 'outer;
568+
received += unsafe{ usize::try_from(*$recvd).expect("overflow") };
569+
if received >= length {
570+
r = 0;
571+
unsafe{ $recvd.write(received.try_into().expect("overflow")) };
572+
break;
573+
}
574+
offset = received.saturating_sub(stage);
572575
}
573576
let error_kind = std::io::Error::last_os_error().kind();
574577
if error_kind == std::io::ErrorKind::WouldBlock {
@@ -802,8 +805,7 @@ macro_rules! impl_nio_write_iovec {
802805
);
803806
if r != windows_sys::Win32::Networking::WinSock::SOCKET_ERROR {
804807
$crate::syscall::reset_errno();
805-
// WSASend returns 0 on success; actual byte count is in *$sent
806-
sent += unsafe { *$sent } as usize;
808+
sent += unsafe{ usize::try_from(*$sent).expect("overflow")};
807809
if sent >= length {
808810
r = 0;
809811
unsafe{ $sent.write(sent.try_into().expect("overflow")) };

0 commit comments

Comments
 (0)