summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Zhakov <ivan@apache.org>2019-06-07 12:01:28 +0000
committerIvan Zhakov <ivan@apache.org>2019-06-07 12:01:28 +0000
commitbe81d32ebf4ab1c7c263500180b240036e48102e (patch)
treecdb47d25a498783873edc9049f6f072e85deb8fa
parentb569ef6670876221b83f10403e89d477dd1c18aa (diff)
downloadapr-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.c12
-rw-r--r--test/testdir.c52
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;
}