From c8ab24bb924bf3aa555cb4400ccbed31a6b3d8f0 Mon Sep 17 00:00:00 2001 From: muflub Date: Thu, 5 Jan 2017 15:16:48 -0800 Subject: [PATCH] fs: fix crash in uv_fs_scandir_next MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-By: Santiago Gimeno Reviewed-By: Saúl Ibarra Corretgé --- src/uv-common.c | 12 +++++++++++- test/test-fs.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ test/test-list.h | 2 ++ 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/uv-common.c b/src/uv-common.c index 46d95467..bc7d1379 100644 --- a/src/uv-common.c +++ b/src/uv-common.c @@ -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; diff --git a/test/test-fs.c b/test/test-fs.c index 70a23999..030245ea 100644 --- a/test/test-fs.c +++ b/test/test-fs.c @@ -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; diff --git a/test/test-list.h b/test/test-list.h index be3f9069..d2fc022b 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -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)