fs: fix crash in uv_fs_scandir_next

Handle the case when it's called after the request has ended, or in case
it ended with an error.

PR-URL: https://github.com/libuv/libuv/pull/1181
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com>
This commit is contained in:
muflub 2017-01-05 15:16:48 -08:00 committed by Saúl Ibarra Corretgé
parent d251dee33b
commit c8ab24bb92
3 changed files with 58 additions and 1 deletions

View File

@ -512,8 +512,18 @@ void uv__fs_scandir_cleanup(uv_fs_t* req) {
int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) {
uv__dirent_t** dents;
uv__dirent_t* dent;
unsigned int* nbufs;
unsigned int* nbufs = uv__get_nbufs(req);
/* Check to see if req passed */
if (req->result < 0)
return req->result;
/* Ptr will be null if req was canceled or no files found */
if (!req->ptr)
return UV_EOF;
nbufs = uv__get_nbufs(req);
assert(nbufs);
dents = req->ptr;

View File

@ -510,6 +510,18 @@ static void empty_scandir_cb(uv_fs_t* req) {
scandir_cb_count++;
}
static void non_existent_scandir_cb(uv_fs_t* req) {
uv_dirent_t dent;
ASSERT(req == &scandir_req);
ASSERT(req->fs_type == UV_FS_SCANDIR);
ASSERT(req->result == UV_ENOENT);
ASSERT(req->ptr == NULL);
ASSERT(UV_ENOENT == uv_fs_scandir_next(req, &dent));
uv_fs_req_cleanup(req);
scandir_cb_count++;
}
static void file_scandir_cb(uv_fs_t* req) {
ASSERT(req == &scandir_req);
@ -2175,6 +2187,39 @@ TEST_IMPL(fs_scandir_empty_dir) {
}
TEST_IMPL(fs_scandir_non_existent_dir) {
const char* path;
uv_fs_t req;
uv_dirent_t dent;
int r;
path = "./non_existent_dir/";
loop = uv_default_loop();
uv_fs_rmdir(NULL, &req, path, NULL);
uv_fs_req_cleanup(&req);
/* Fill the req to ensure that required fields are cleaned up */
memset(&req, 0xdb, sizeof(req));
r = uv_fs_scandir(NULL, &req, path, 0, NULL);
ASSERT(r == UV_ENOENT);
ASSERT(req.result == UV_ENOENT);
ASSERT(req.ptr == NULL);
ASSERT(UV_ENOENT == uv_fs_scandir_next(&req, &dent));
uv_fs_req_cleanup(&req);
r = uv_fs_scandir(loop, &scandir_req, path, 0, non_existent_scandir_cb);
ASSERT(r == 0);
ASSERT(scandir_cb_count == 0);
uv_run(loop, UV_RUN_DEFAULT);
ASSERT(scandir_cb_count == 1);
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(fs_scandir_file) {
const char* path;
int r;

View File

@ -295,6 +295,7 @@ TEST_DECLARE (fs_event_start_and_close)
TEST_DECLARE (fs_event_error_reporting)
TEST_DECLARE (fs_event_getpath)
TEST_DECLARE (fs_scandir_empty_dir)
TEST_DECLARE (fs_scandir_non_existent_dir)
TEST_DECLARE (fs_scandir_file)
TEST_DECLARE (fs_open_dir)
TEST_DECLARE (fs_rename_to_existing_file)
@ -751,6 +752,7 @@ TASK_LIST_START
TEST_ENTRY (fs_event_error_reporting)
TEST_ENTRY (fs_event_getpath)
TEST_ENTRY (fs_scandir_empty_dir)
TEST_ENTRY (fs_scandir_non_existent_dir)
TEST_ENTRY (fs_scandir_file)
TEST_ENTRY (fs_open_dir)
TEST_ENTRY (fs_rename_to_existing_file)