diff options
author | Ivan Zhakov <ivan@apache.org> | 2019-06-07 12:01:28 +0000 |
---|---|---|
committer | Ivan Zhakov <ivan@apache.org> | 2019-06-07 12:01:28 +0000 |
commit | be81d32ebf4ab1c7c263500180b240036e48102e (patch) | |
tree | cdb47d25a498783873edc9049f6f072e85deb8fa | |
parent | b569ef6670876221b83f10403e89d477dd1c18aa (diff) | |
download | apr-be81d32ebf4ab1c7c263500180b240036e48102e.tar.gz |
Windows platform: Fix access to uninitialized memory in apr_dir_read() when
wanted is more than APR_FINFO_MIN.
git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1860747 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | file_io/win32/dir.c | 12 | ||||
-rw-r--r-- | test/testdir.c | 52 |
2 files changed, 63 insertions, 1 deletions
diff --git a/file_io/win32/dir.c b/file_io/win32/dir.c index 35860b61d..6ddcfe64b 100644 --- a/file_io/win32/dir.c +++ b/file_io/win32/dir.c @@ -172,8 +172,18 @@ APR_DECLARE(apr_status_t) apr_dir_read(apr_finfo_t *finfo, apr_int32_t wanted, /* Almost all our work is done. Tack on the wide file name * to the end of the wdirname (already / delimited) */ - if (!eos) + if (!eos) { + /* It's more efficient to store WDIRNAME in THEDIR, + * but let's make simple fix first. */ + if ((rv = utf8_to_unicode_path(wdirname, sizeof(wdirname) + / sizeof(apr_wchar_t), + thedir->dirname))) { + return rv; + } + eos = wcschr(wdirname, '\0'); + } + wcscpy(eos, thedir->w.entry->cFileName); rv = more_finfo(finfo, wdirname, wanted, MORE_OF_WFSPEC); eos[0] = '\0'; diff --git a/test/testdir.c b/test/testdir.c index 87085bd0a..21876be5d 100644 --- a/test/testdir.c +++ b/test/testdir.c @@ -378,6 +378,57 @@ static void test_rmkdir_nocwd(abts_case *tc, void *data) APR_ASSERT_SUCCESS(tc, "remove cwd", apr_dir_remove(path, p)); } +static void test_readmore_info(abts_case* tc, void* data) +{ + apr_status_t rv; + apr_dir_t* dir; + apr_file_t* thefile; + apr_finfo_t finfo; + /* Ask for information that is not stored in dirent. */ + apr_uint32_t wanted = APR_FINFO_MIN | APR_FINFO_OWNER; + + rv = apr_dir_make("dir1", + APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_UEXECUTE, + p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_file_open(&thefile, "dir1/file1", + APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_CREATE, + APR_FPROT_OS_DEFAULT, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + rv = apr_file_close(thefile); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_file_open(&thefile, "dir1/file2", + APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_CREATE, + APR_FPROT_OS_DEFAULT, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + rv = apr_file_close(thefile); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_dir_open(&dir, "dir1", p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + while (1) { + rv = apr_dir_read(&finfo, wanted, dir); + if (APR_STATUS_IS_ENOENT(rv)) + break; + + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_TRUE(tc, finfo.valid & wanted); + } + + apr_dir_close(dir); + + rv = apr_file_remove("dir1/file1", p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_file_remove("dir1/file2", p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_dir_remove("dir1", p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); +} abts_suite *testdir(abts_suite *suite) { @@ -399,6 +450,7 @@ abts_suite *testdir(abts_suite *suite) abts_run_test(suite, test_opendir_notthere, NULL); abts_run_test(suite, test_closedir, NULL); abts_run_test(suite, test_uncleared_errno, NULL); + abts_run_test(suite, test_readmore_info, NULL); return suite; } |