From c6d43bea09093545e0f199921b2d33548a2a1f85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Mon, 25 Nov 2024 15:10:47 +0100 Subject: [PATCH] unix,win: harmonize buffer checking For any API that takes a buffer and size pointer, check both pointers and the pointed-to size and return UV_EINVAL in case of error. Example: ``` int uv_foo(char* buffer, size_t* size) { if (buffer == NULL || size == NULL || *size == 0) return UV_EINVAL; ... } ``` In order to "peek" the necessary size for dynamic allocation, the following pattern can be used: ``` char *buf; char scratch[1]; size_t len = sizeof(scratch); int r; r = uv_foo(scratch, &len); assert(r == UV_ENOBUFS); buf = malloc(len); r = uv_foo(buf, &len); ... ``` --- src/fs-poll.c | 3 +++ src/unix/core.c | 2 +- src/uv-common.c | 3 +++ src/win/pipe.c | 12 +++++++++--- src/win/util.c | 4 ++-- test/test-fs-event.c | 2 +- 6 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/fs-poll.c b/src/fs-poll.c index 1bac1c56..44f6263a 100644 --- a/src/fs-poll.c +++ b/src/fs-poll.c @@ -139,6 +139,9 @@ int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buffer, size_t* size) { struct poll_ctx* ctx; size_t required_len; + if (buffer == NULL || size == NULL || *size == 0) + return UV_EINVAL; + if (!uv_is_active((uv_handle_t*)handle)) { *size = 0; return UV_EINVAL; diff --git a/src/unix/core.c b/src/unix/core.c index 0c52ccf2..66053780 100644 --- a/src/unix/core.c +++ b/src/unix/core.c @@ -751,7 +751,7 @@ ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) { int uv_cwd(char* buffer, size_t* size) { char scratch[1 + UV__PATH_MAX]; - if (buffer == NULL || size == NULL) + if (buffer == NULL || size == NULL || *size == 0) return UV_EINVAL; /* Try to read directly into the user's buffer first... */ diff --git a/src/uv-common.c b/src/uv-common.c index 2200fe3f..327e142c 100644 --- a/src/uv-common.c +++ b/src/uv-common.c @@ -644,6 +644,9 @@ int uv_send_buffer_size(uv_handle_t* handle, int *value) { int uv_fs_event_getpath(uv_fs_event_t* handle, char* buffer, size_t* size) { size_t required_len; + if (buffer == NULL || size == NULL || *size == 0) + return UV_EINVAL; + if (!uv__is_active(handle)) { *size = 0; return UV_EINVAL; diff --git a/src/win/pipe.c b/src/win/pipe.c index d46ecb9f..d05bfd28 100644 --- a/src/win/pipe.c +++ b/src/win/pipe.c @@ -1161,9 +1161,9 @@ int uv__pipe_accept(uv_pipe_t* server, uv_stream_t* client) { err = uv__tcp_xfer_import( (uv_tcp_t*) client, item->xfer_type, &item->xfer_info); - + uv__free(item); - + if (err != 0) return err; @@ -1738,7 +1738,7 @@ static DWORD uv__pipe_get_ipc_remote_pid(uv_pipe_t* handle) { GetNamedPipeServerProcessId(handle->handle, pid); } } - + return *pid; } @@ -2602,6 +2602,9 @@ int uv_pipe_pending_count(uv_pipe_t* handle) { int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size) { + if (buffer == NULL || size == NULL || *size == 0) + return UV_EINVAL; + if (handle->flags & UV_HANDLE_BOUND) return uv__pipe_getname(handle, buffer, size); @@ -2616,6 +2619,9 @@ int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size) { int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) { + if (buffer == NULL || size == NULL || *size == 0) + return UV_EINVAL; + /* emulate unix behaviour */ if (handle->flags & UV_HANDLE_BOUND) return UV_ENOTCONN; diff --git a/src/win/util.c b/src/win/util.c index e0dba1aa..d7b5f661 100644 --- a/src/win/util.c +++ b/src/win/util.c @@ -191,7 +191,7 @@ int uv_cwd(char* buffer, size_t* size) { WCHAR *utf16_buffer; int r; - if (buffer == NULL || size == NULL) { + if (buffer == NULL || size == NULL || *size == 0) { return UV_EINVAL; } @@ -1589,7 +1589,7 @@ int uv_os_uname(uv_utsname_t* buffer) { version_size = sizeof(buffer->version) - version_size; r = uv__copy_utf16_to_utf8(os_info.szCSDVersion, -1, - buffer->version + + buffer->version + sizeof(buffer->version) - version_size, &version_size); if (r) diff --git a/test/test-fs-event.c b/test/test-fs-event.c index bb223a5f..85649cbc 100644 --- a/test/test-fs-event.c +++ b/test/test-fs-event.c @@ -1121,7 +1121,7 @@ TEST_IMPL(fs_event_getpath) { ASSERT_EQ(r, UV_EINVAL); r = uv_fs_event_start(&fs_event, fail_cb, watch_dir[i], 0); ASSERT_OK(r); - len = 0; + len = 1; r = uv_fs_event_getpath(&fs_event, buf, &len); ASSERT_EQ(r, UV_ENOBUFS); ASSERT_LT(len, sizeof buf); /* sanity check */