unix,windows: init all requests in fs calls

Prior to this change, several of the fs functions checked for
invalid arguments before initializing the fs request. If a
consumer received a UV_EINVAL from one of these functions, and
then called uv_fs_req_cleanup(), the application would crash, as
the pointer being freed was not allocated. This commit makes
sure that all fs functions initialize the request before returning.

Fixes: https://github.com/libuv/libuv/issues/1508
PR-URL: https://github.com/libuv/libuv/pull/1509
Reviewed-By: Bartosz Sosnowski <bartosz@janeasystems.com>
Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com>
This commit is contained in:
cjihrig 2017-08-25 09:58:32 -04:00
parent 165c63b96c
commit 7a0e64d2e0
No known key found for this signature in database
GPG Key ID: 7434390BDBE9B9C5
4 changed files with 24 additions and 15 deletions

View File

@ -1287,10 +1287,11 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req,
unsigned int nbufs,
int64_t off,
uv_fs_cb cb) {
INIT(READ);
if (bufs == NULL || nbufs == 0)
return -EINVAL;
INIT(READ);
req->file = file;
req->nbufs = nbufs;
@ -1425,10 +1426,11 @@ int uv_fs_write(uv_loop_t* loop,
unsigned int nbufs,
int64_t off,
uv_fs_cb cb) {
INIT(WRITE);
if (bufs == NULL || nbufs == 0)
return -EINVAL;
INIT(WRITE);
req->file = file;
req->nbufs = nbufs;
@ -1476,10 +1478,11 @@ int uv_fs_copyfile(uv_loop_t* loop,
const char* new_path,
int flags,
uv_fs_cb cb) {
INIT(COPYFILE);
if (flags & ~UV_FS_COPYFILE_EXCL)
return -EINVAL;
INIT(COPYFILE);
PATH2;
req->flags = flags;
POST;

View File

@ -2010,11 +2010,11 @@ int uv_fs_read(uv_loop_t* loop,
unsigned int nbufs,
int64_t offset,
uv_fs_cb cb) {
uv_fs_req_init(loop, req, UV_FS_READ, cb);
if (bufs == NULL || nbufs == 0)
return UV_EINVAL;
uv_fs_req_init(loop, req, UV_FS_READ, cb);
req->file.fd = fd;
req->fs.info.nbufs = nbufs;
@ -2046,11 +2046,11 @@ int uv_fs_write(uv_loop_t* loop,
unsigned int nbufs,
int64_t offset,
uv_fs_cb cb) {
uv_fs_req_init(loop, req, UV_FS_WRITE, cb);
if (bufs == NULL || nbufs == 0)
return UV_EINVAL;
uv_fs_req_init(loop, req, UV_FS_WRITE, cb);
req->file.fd = fd;
req->fs.info.nbufs = nbufs;
@ -2251,12 +2251,12 @@ int uv_fs_realpath(uv_loop_t* loop, uv_fs_t* req, const char* path,
uv_fs_cb cb) {
int err;
if (!req || !path) {
uv_fs_req_init(loop, req, UV_FS_REALPATH, cb);
if (!path) {
return UV_EINVAL;
}
uv_fs_req_init(loop, req, UV_FS_REALPATH, cb);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
@ -2435,10 +2435,11 @@ int uv_fs_copyfile(uv_loop_t* loop,
uv_fs_cb cb) {
int err;
uv_fs_req_init(loop, req, UV_FS_COPYFILE, cb);
if (flags & ~UV_FS_COPYFILE_EXCL)
return UV_EINVAL;
uv_fs_req_init(loop, req, UV_FS_COPYFILE, cb);
err = fs__capture_path(req, path, new_path, cb != NULL);
if (err)

View File

@ -99,6 +99,7 @@ TEST_IMPL(fs_copyfile) {
/* Fails with EINVAL if bad flags are passed. */
r = uv_fs_copyfile(NULL, &req, src, dst, -1, NULL);
ASSERT(r == UV_EINVAL);
uv_fs_req_cleanup(&req);
/* Fails with ENOENT if source does not exist. */
unlink(src);

View File

@ -2751,19 +2751,23 @@ TEST_IMPL(fs_write_alotof_bufs_with_offset) {
TEST_IMPL(fs_read_write_null_arguments) {
int r;
r = uv_fs_read(NULL, NULL, 0, NULL, 0, -1, NULL);
r = uv_fs_read(NULL, &read_req, 0, NULL, 0, -1, NULL);
ASSERT(r == UV_EINVAL);
uv_fs_req_cleanup(&read_req);
r = uv_fs_write(NULL, NULL, 0, NULL, 0, -1, NULL);
r = uv_fs_write(NULL, &write_req, 0, NULL, 0, -1, NULL);
ASSERT(r == UV_EINVAL);
uv_fs_req_cleanup(&write_req);
iov = uv_buf_init(NULL, 0);
r = uv_fs_read(NULL, NULL, 0, &iov, 0, -1, NULL);
r = uv_fs_read(NULL, &read_req, 0, &iov, 0, -1, NULL);
ASSERT(r == UV_EINVAL);
uv_fs_req_cleanup(&read_req);
iov = uv_buf_init(NULL, 0);
r = uv_fs_write(NULL, NULL, 0, &iov, 0, -1, NULL);
r = uv_fs_write(NULL, &write_req, 0, &iov, 0, -1, NULL);
ASSERT(r == UV_EINVAL);
uv_fs_req_cleanup(&write_req);
return 0;
}