fixup! io: make libuv 64-bit safe
This commit is contained in:
parent
533a669ac6
commit
58edef0ca9
@ -520,33 +520,35 @@ static int uv__fs_read(uv_fs_t* req) {
|
||||
if (nbufs > iovmax)
|
||||
nbufs = iovmax;
|
||||
|
||||
/* Truncate multi-buf reads to IO_MAX_BYTES total, dropping trailing bufs. */
|
||||
/* Truncate multi-buf reads to UV__IO_MAX_BYTES total, dropping trailing bufs. */
|
||||
if (nbufs > 1) {
|
||||
size_t total;
|
||||
size_t n;
|
||||
for (total = 0, n = 0; n < nbufs; n++) {
|
||||
if (bufs[n].iov_len > IO_MAX_BYTES - total)
|
||||
if (bufs[n].iov_len > UV__IO_MAX_BYTES - total)
|
||||
break;
|
||||
total += bufs[n].iov_len;
|
||||
}
|
||||
if (n < nbufs)
|
||||
nbufs = n > 0 ? n : 1;
|
||||
nbufs = n > 0 ? n : 1;
|
||||
}
|
||||
|
||||
r = 0;
|
||||
if (off < 0) {
|
||||
if (nbufs == 1)
|
||||
if (nbufs == 1) {
|
||||
r = read(fd, bufs->iov_base,
|
||||
bufs->iov_len > IO_MAX_BYTES ? IO_MAX_BYTES : bufs->iov_len);
|
||||
else if (nbufs > 1)
|
||||
bufs->iov_len > UV__IO_MAX_BYTES ? UV__IO_MAX_BYTES : bufs->iov_len);
|
||||
} else if (nbufs > 1) {
|
||||
r = readv(fd, bufs, nbufs);
|
||||
}
|
||||
} else {
|
||||
if (nbufs == 1)
|
||||
if (nbufs == 1) {
|
||||
r = pread(fd, bufs->iov_base,
|
||||
bufs->iov_len > IO_MAX_BYTES ? IO_MAX_BYTES : bufs->iov_len,
|
||||
bufs->iov_len > UV__IO_MAX_BYTES ? UV__IO_MAX_BYTES : bufs->iov_len,
|
||||
off);
|
||||
else if (nbufs > 1)
|
||||
}
|
||||
else if (nbufs > 1) {
|
||||
r = uv__preadv(fd, bufs, nbufs, off);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __PASE__
|
||||
@ -2166,7 +2168,7 @@ int uv_fs_sendfile(uv_loop_t* loop,
|
||||
req->flags = in_fd; /* hack */
|
||||
req->file = out_fd;
|
||||
req->off = off;
|
||||
if (len > IO_MAX_BYTES)
|
||||
if (len > UV__IO_MAX_BYTES)
|
||||
return UV_EINVAL;
|
||||
req->bufsml[0].len = len;
|
||||
POST;
|
||||
@ -2235,7 +2237,7 @@ int uv_fs_write(uv_loop_t* loop,
|
||||
if (bufs == NULL || nbufs == 0)
|
||||
return UV_EINVAL;
|
||||
|
||||
if (uv__count_bufs(bufs, nbufs) > IO_MAX_BYTES)
|
||||
if (uv__count_bufs(bufs, nbufs) > UV__IO_MAX_BYTES)
|
||||
return UV_EINVAL;
|
||||
|
||||
req->file = file;
|
||||
|
||||
@ -78,7 +78,6 @@ static size_t uv__write_req_size(uv_write_t* req);
|
||||
static void uv__drain(uv_stream_t* stream);
|
||||
|
||||
|
||||
|
||||
void uv__stream_init(uv_loop_t* loop,
|
||||
uv_stream_t* stream,
|
||||
uv_handle_type type) {
|
||||
@ -1058,15 +1057,15 @@ static void uv__read(uv_stream_t* stream) {
|
||||
assert(uv__stream_fd(stream) >= 0);
|
||||
|
||||
if (!is_ipc) {
|
||||
do
|
||||
do {
|
||||
nread = read(uv__stream_fd(stream),
|
||||
buf.base,
|
||||
buf.len > IO_MAX_BYTES ? IO_MAX_BYTES : buf.len);
|
||||
while (nread < 0 && errno == EINTR);
|
||||
buf.len > UV__IO_MAX_BYTES ? UV__IO_MAX_BYTES : buf.len);
|
||||
} while (nread < 0 && errno == EINTR);
|
||||
} else {
|
||||
/* ipc uses recvmsg */
|
||||
if (buf.len > IO_MAX_BYTES)
|
||||
buf.len = IO_MAX_BYTES;
|
||||
if (buf.len > UV__IO_MAX_BYTES)
|
||||
buf.len = UV__IO_MAX_BYTES;
|
||||
msg.msg_flags = 0;
|
||||
msg.msg_iov = (struct iovec*) &buf;
|
||||
msg.msg_iovlen = 1;
|
||||
@ -1078,8 +1077,7 @@ static void uv__read(uv_stream_t* stream) {
|
||||
|
||||
do {
|
||||
nread = uv__recvmsg(uv__stream_fd(stream), &msg, 0);
|
||||
}
|
||||
while (nread < 0 && errno == EINTR);
|
||||
} while (nread < 0 && errno == EINTR);
|
||||
}
|
||||
|
||||
if (nread < 0) {
|
||||
@ -1314,11 +1312,11 @@ static int uv__check_before_write(uv_stream_t* stream,
|
||||
if (nbufs < 1 || nbufs > 1024*1024)
|
||||
return UV_EINVAL;
|
||||
|
||||
/* Reject writes above IO_MAX_BYTES to be consistent with EINVAL on platforms
|
||||
/* Reject writes above UV__IO_MAX_BYTES to be consistent with EINVAL on platforms
|
||||
* such as macOS that fail when the total size of the iov exceeds 2GB,
|
||||
* and catch/prevent sign-extension bugs.
|
||||
*/
|
||||
if (uv__count_bufs(bufs, nbufs) > IO_MAX_BYTES)
|
||||
if (uv__count_bufs(bufs, nbufs) > UV__IO_MAX_BYTES)
|
||||
return UV_EINVAL;
|
||||
|
||||
if (uv__stream_fd(stream) < 0)
|
||||
|
||||
@ -486,7 +486,7 @@ int uv__udp_check_before_send(uv_udp_t* handle,
|
||||
if (nbufs < 1 || nbufs > 1024 * 1024)
|
||||
return UV_EINVAL;
|
||||
|
||||
if (uv__count_bufs(bufs, nbufs) > IO_MAX_BYTES)
|
||||
if (uv__count_bufs(bufs, nbufs) > UV__IO_MAX_BYTES)
|
||||
return UV_EINVAL;
|
||||
|
||||
return addrlen;
|
||||
|
||||
@ -230,7 +230,7 @@ size_t uv__count_bufs(const uv_buf_t bufs[], unsigned int nbufs);
|
||||
* an EINVAL. On Linux, IO syscalls will transfer at most this many bytes.
|
||||
* Use this limit everywhere to avoid platform-specific failures.
|
||||
*/
|
||||
#define IO_MAX_BYTES 0x7ffff000
|
||||
#define UV__IO_MAX_BYTES 0x7ffff000
|
||||
|
||||
int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value);
|
||||
|
||||
|
||||
@ -898,8 +898,8 @@ void fs__read(uv_fs_t* req) {
|
||||
}
|
||||
|
||||
to_read = req->fs.info.bufs[index].len;
|
||||
if (to_read > IO_MAX_BYTES)
|
||||
to_read = IO_MAX_BYTES;
|
||||
if (to_read > UV__IO_MAX_BYTES)
|
||||
to_read = UV__IO_MAX_BYTES;
|
||||
result = ReadFile(handle,
|
||||
req->fs.info.bufs[index].base,
|
||||
to_read,
|
||||
@ -3333,7 +3333,7 @@ int uv_fs_write(uv_loop_t* loop,
|
||||
return UV_EINVAL;
|
||||
}
|
||||
|
||||
if (uv__count_bufs(bufs, nbufs) > IO_MAX_BYTES) {
|
||||
if (uv__count_bufs(bufs, nbufs) > UV__IO_MAX_BYTES) {
|
||||
SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
|
||||
return UV_EINVAL;
|
||||
}
|
||||
@ -3707,7 +3707,7 @@ int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file fd_out,
|
||||
req->file.fd = fd_in;
|
||||
req->fs.info.fd_out = fd_out;
|
||||
req->fs.info.offset = in_offset;
|
||||
if (length > IO_MAX_BYTES)
|
||||
if (length > UV__IO_MAX_BYTES)
|
||||
return UV_EINVAL;
|
||||
req->fs.info.bufsml[0].len = length;
|
||||
POST;
|
||||
|
||||
@ -1622,7 +1622,7 @@ static int uv__pipe_write_data(uv_loop_t* loop,
|
||||
return err;
|
||||
}
|
||||
|
||||
if (write_buf.len > IO_MAX_BYTES)
|
||||
if (write_buf.len > UV__IO_MAX_BYTES)
|
||||
return ERROR_INVALID_PARAMETER; /* Maps to UV_EINVAL. */
|
||||
|
||||
if ((handle->flags &
|
||||
@ -1972,10 +1972,10 @@ static int uv__pipe_read_data(uv_loop_t* loop,
|
||||
* (a) the length of the user-allocated buffer.
|
||||
* (b) the maximum data length as specified by the `max_bytes` argument.
|
||||
* (c) the amount of data that can be read non-blocking.
|
||||
* (d) IO_MAX_BYTES.
|
||||
* (d) UV__IO_MAX_BYTES.
|
||||
*/
|
||||
if (buf.len > IO_MAX_BYTES)
|
||||
buf.len = IO_MAX_BYTES;
|
||||
if (buf.len > UV__IO_MAX_BYTES)
|
||||
buf.len = UV__IO_MAX_BYTES;
|
||||
if (max_bytes > buf.len)
|
||||
max_bytes = buf.len;
|
||||
|
||||
|
||||
@ -122,7 +122,7 @@ static int uv__check_before_write(uv_stream_t* handle,
|
||||
return UV_EINVAL;
|
||||
}
|
||||
|
||||
if (uv__count_bufs(bufs, nbufs) > IO_MAX_BYTES) {
|
||||
if (uv__count_bufs(bufs, nbufs) > UV__IO_MAX_BYTES) {
|
||||
return UV_EINVAL;
|
||||
}
|
||||
|
||||
|
||||
@ -1103,8 +1103,8 @@ void uv__process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,
|
||||
break;
|
||||
}
|
||||
assert(buf.base != NULL);
|
||||
if (buf.len > IO_MAX_BYTES)
|
||||
buf.len = IO_MAX_BYTES;
|
||||
if (buf.len > UV__IO_MAX_BYTES)
|
||||
buf.len = UV__IO_MAX_BYTES;
|
||||
|
||||
flags = 0;
|
||||
if (WSARecv(handle->socket,
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
/* Verify that passing INT32_MAX as a buffer length is rejected with UV_EINVAL
|
||||
* at the various I/O entry points that enforce IO_MAX_BYTES.
|
||||
* at the various I/O entry points that enforce UV__IO_MAX_BYTES.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
@ -59,17 +59,17 @@ TEST_IMPL(io_64_safe) {
|
||||
|
||||
loop = uv_default_loop();
|
||||
|
||||
/* A buf whose length just exceeds IO_MAX_BYTES (0x7ffff000). */
|
||||
/* A buf whose length just exceeds UV__IO_MAX_BYTES (0x7ffff000). */
|
||||
buf = uv_buf_init(NULL, INT32_MAX);
|
||||
|
||||
/* Two buffers whose individual sizes are reasonable but whose sum exceeds
|
||||
* IO_MAX_BYTES (0x7ffff000). Each is 1 GiB + 1 byte.
|
||||
* UV__IO_MAX_BYTES (0x7ffff000). Each is 1 GiB + 1 byte.
|
||||
*/
|
||||
bufs2[0] = uv_buf_init(NULL, 0x40000001u);
|
||||
bufs2[1] = uv_buf_init(NULL, 0x40000001u);
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* uv_fs_write: reject synchronous filesystem write > IO_MAX_BYTES. */
|
||||
/* uv_fs_write: reject synchronous filesystem write > UV__IO_MAX_BYTES. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
{
|
||||
fd = uv_fs_open(NULL, &open_req, TEST_FILE,
|
||||
@ -80,7 +80,7 @@ TEST_IMPL(io_64_safe) {
|
||||
ASSERT_EQ(UV_EINVAL, uv_fs_write(NULL, &fs_req, fd, &buf, 1, 0, NULL));
|
||||
uv_fs_req_cleanup(&fs_req);
|
||||
|
||||
/* nbufs > 1 where sum > IO_MAX_BYTES */
|
||||
/* nbufs > 1 where sum > UV__IO_MAX_BYTES */
|
||||
ASSERT_EQ(UV_EINVAL, uv_fs_write(NULL, &fs_req, fd, bufs2, 2, 0, NULL));
|
||||
uv_fs_req_cleanup(&fs_req);
|
||||
|
||||
@ -89,7 +89,7 @@ TEST_IMPL(io_64_safe) {
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* uv_fs_sendfile: reject len > IO_MAX_BYTES. */
|
||||
/* uv_fs_sendfile: reject len > UV__IO_MAX_BYTES. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
{
|
||||
in_fd = uv_fs_open(NULL, &open_req, TEST_FILE,
|
||||
@ -118,12 +118,12 @@ TEST_IMPL(io_64_safe) {
|
||||
uv_fs_req_cleanup(&fs_req);
|
||||
|
||||
{
|
||||
/* uv_write: reject stream write > IO_MAX_BYTES before queuing. */
|
||||
/* uv_write: reject stream write > UV__IO_MAX_BYTES before queuing. */
|
||||
ASSERT_OK(uv_tcp_init(loop, &tcp));
|
||||
ASSERT_EQ(UV_EINVAL,
|
||||
uv_write(&write_req, (uv_stream_t*) &tcp, &buf, 1, NULL));
|
||||
|
||||
/* nbufs > 1 where sum > IO_MAX_BYTES */
|
||||
/* nbufs > 1 where sum > UV__IO_MAX_BYTES */
|
||||
ASSERT_EQ(UV_EINVAL,
|
||||
uv_write(&write_req, (uv_stream_t*) &tcp, bufs2, 2, NULL));
|
||||
|
||||
@ -140,7 +140,7 @@ TEST_IMPL(io_64_safe) {
|
||||
ASSERT_OK(uv_udp_init(loop, &udp));
|
||||
ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
|
||||
|
||||
/* uv_udp_try_send: reject UDP send > IO_MAX_BYTES. */
|
||||
/* uv_udp_try_send: reject UDP send > UV__IO_MAX_BYTES. */
|
||||
ASSERT_EQ(UV_EINVAL,
|
||||
uv_udp_try_send(&udp, &buf, 1,
|
||||
(const struct sockaddr*) &addr));
|
||||
@ -160,7 +160,7 @@ TEST_IMPL(io_64_safe) {
|
||||
uv_udp_send(&send_req, &udp, bufs2, 2,
|
||||
(const struct sockaddr*) &addr, on_udp_send));
|
||||
|
||||
/* uv_udp_try_send2: reject per-batch size > IO_MAX_BYTES. */
|
||||
/* uv_udp_try_send2: reject per-batch size > UV__IO_MAX_BYTES. */
|
||||
t2_bufs[0] = &buf;
|
||||
t2_nbufs[0] = 1;
|
||||
t2_addrs[0] = (struct sockaddr*) &addr;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user