fs: clobber req->path on uv_fs_mkstemp() error

Contents of template variable passed for posix call mkstemp on error
code EINVAL is unknown. On AIX platform, template will get clobbered
on EINVAL and any attempt to read template might result in error.

In libuv, req->path is passed directly to the mkstemp call and
behavior of this string on error is platform dependent. To avoid
portability issues, it's better to have a common behavior on all
platform. For both unix and windows platform libuv will rewrite path
with an empty string on all error cases.

Fixes: https://github.com/libuv/libuv/issues/2913
Refs: https://github.com/nodejs/node/pull/33549
Refs: https://github.com/libuv/libuv/pull/2933
PR-URL: https://github.com/libuv/libuv/pull/2938
Reviewed-By: Jameson Nash <vtjnash@gmail.com>
This commit is contained in:
tjarlama 2020-08-12 09:57:26 +05:30 committed by GitHub
parent ea92e9c720
commit e208100fc9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 22 additions and 12 deletions

View File

@ -306,7 +306,8 @@ static int uv__fs_mkstemp(uv_fs_t* req) {
if (path_length < pattern_size ||
strcmp(path + path_length - pattern_size, pattern)) {
errno = EINVAL;
return -1;
r = -1;
goto clobber;
}
uv_once(&once, uv__mkostemp_initonce);
@ -321,7 +322,7 @@ static int uv__fs_mkstemp(uv_fs_t* req) {
/* If mkostemp() returns EINVAL, it means the kernel doesn't
support O_CLOEXEC, so we just fallback to mkstemp() below. */
if (errno != EINVAL)
return r;
goto clobber;
/* We set the static variable so that next calls don't even
try to use mkostemp. */
@ -347,6 +348,9 @@ static int uv__fs_mkstemp(uv_fs_t* req) {
if (req->cb != NULL)
uv_rwlock_rdunlock(&req->loop->cloexec_lock);
clobber:
if (r < 0)
path[0] = '\0';
return r;
}

View File

@ -1241,19 +1241,21 @@ void fs__mktemp(uv_fs_t* req, uv__fs_mktemp_func func) {
unsigned int tries, i;
size_t len;
uint64_t v;
char* path;
path = req->path;
len = wcslen(req->file.pathw);
ep = req->file.pathw + len;
if (len < num_x || wcsncmp(ep - num_x, L"XXXXXX", num_x)) {
SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
return;
goto clobber;
}
tries = TMP_MAX;
do {
if (uv__random_rtlgenrandom((void *)&v, sizeof(v)) < 0) {
SET_REQ_UV_ERROR(req, UV_EIO, ERROR_IO_DEVICE);
break;
goto clobber;
}
cp = ep - num_x;
@ -1264,16 +1266,17 @@ void fs__mktemp(uv_fs_t* req, uv__fs_mktemp_func func) {
if (func(req)) {
if (req->result >= 0) {
len = strlen(req->path);
wcstombs((char*) req->path + len - num_x, ep - num_x, num_x);
len = strlen(path);
wcstombs(path + len - num_x, ep - num_x, num_x);
}
break;
return;
}
} while (--tries);
if (tries == 0) {
SET_REQ_WIN32_ERROR(req, GetLastError());
}
SET_REQ_WIN32_ERROR(req, GetLastError());
clobber:
path[0] = '\0';
}

View File

@ -1290,7 +1290,10 @@ TEST_IMPL(fs_mkstemp) {
ASSERT(strcmp(mkstemp_req1.path, mkstemp_req2.path) != 0);
/* invalid template returns EINVAL */
ASSERT(uv_fs_mkstemp(NULL, &mkstemp_req3, "test_file", NULL) == UV_EINVAL);
ASSERT_EQ(UV_EINVAL, uv_fs_mkstemp(NULL, &mkstemp_req3, "test_file", NULL));
/* Make sure that path is empty string */
ASSERT_EQ(0, strlen(mkstemp_req3.path));
/* We can write to the opened file */
iov = uv_buf_init(test_buf, sizeof(test_buf));