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);
...
```
This commit is contained in:
Saúl Ibarra Corretgé 2024-11-25 15:10:47 +01:00 committed by GitHub
parent 31ea3411cc
commit c6d43bea09
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 19 additions and 7 deletions

View File

@ -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;

View File

@ -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... */

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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 */