summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjorton <jorton@13f79535-47bb-0310-9956-ffa450edef68>2019-07-02 15:58:19 +0000
committerjorton <jorton@13f79535-47bb-0310-9956-ffa450edef68>2019-07-02 15:58:19 +0000
commit6ae440b73cb0efc7be2dd47278294140c67fa59f (patch)
treeab25ac68f06b5426d1d402196046645e2a6e8d8e
parent3f168944d6f5a7a8b2631e8c7fe07047b1344093 (diff)
downloadlibapr-6ae440b73cb0efc7be2dd47278294140c67fa59f.tar.gz
* include/apr_file_info.h: Clarify pool handling for apr_dir_read and
apr_dir_pread. * file_io/win32/dir.c, file_io/os2/dir.c (apr_dir_read): Duplicate the returned filename so the call has no side-effects on apr_finfo_t structures passed to previous invocations of the function. * test/testdir.c (test_read_side_effects): Add test case for side-effects of apr_dir_read. git-svn-id: http://svn.apache.org/repos/asf/apr/apr/trunk@1862435 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--CHANGES3
-rw-r--r--file_io/os2/dir.c2
-rw-r--r--file_io/win32/dir.c2
-rw-r--r--include/apr_file_info.h12
-rw-r--r--test/testdir.c32
5 files changed, 46 insertions, 5 deletions
diff --git a/CHANGES b/CHANGES
index 9b6655828..0e181364d 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,9 @@
-*- coding: utf-8 -*-
Changes for APR 2.0.0
+ *) apr_dir_read(): The returned finfo->name field is now duplicated
+ into the pool for all implementations. [Joe Orton]
+
*) apr_dir_pread(): Add function which restricts per-read memory
consumption to a different pool to the apr_dir_t object.
[Joe Orton]
diff --git a/file_io/os2/dir.c b/file_io/os2/dir.c
index d1a0072cc..c26f39d1f 100644
--- a/file_io/os2/dir.c
+++ b/file_io/os2/dir.c
@@ -122,7 +122,7 @@ APR_DECLARE(apr_status_t) apr_dir_pread(apr_finfo_t *finfo, apr_int32_t wanted,
apr_os2_time_to_apr_time(&finfo->ctime, thedir->entry.fdateCreation,
thedir->entry.ftimeCreation);
- finfo->name = thedir->entry.achName;
+ finfo->name = apr_pstrdup(pool, thedir->entry.achName);
finfo->valid = APR_FINFO_NAME | APR_FINFO_MTIME | APR_FINFO_ATIME |
APR_FINFO_CTIME | APR_FINFO_TYPE | APR_FINFO_SIZE |
APR_FINFO_CSIZE;
diff --git a/file_io/win32/dir.c b/file_io/win32/dir.c
index 1703ac4b3..b02c9cdfd 100644
--- a/file_io/win32/dir.c
+++ b/file_io/win32/dir.c
@@ -152,7 +152,7 @@ APR_DECLARE(apr_status_t) apr_dir_pread(apr_finfo_t *finfo, apr_int32_t wanted,
if ((rv = unicode_to_utf8_path(thedir->name, APR_FILE_MAX * 3 + 1,
thedir->entry->cFileName)))
return rv;
- fname = thedir->name;
+ fname = apr_pstrdup(pool, thedir->name);
fillin_fileinfo(finfo, (WIN32_FILE_ATTRIBUTE_DATA *) thedir->entry,
0, 1, fname, wanted);
diff --git a/include/apr_file_info.h b/include/apr_file_info.h
index f08762cea..0cf34ff06 100644
--- a/include/apr_file_info.h
+++ b/include/apr_file_info.h
@@ -257,15 +257,18 @@ APR_DECLARE(apr_status_t) apr_dir_close(apr_dir_t *thedir);
* @param wanted The desired apr_finfo_t fields, as a bit flag of APR_FINFO_
values
* @param thedir the directory descriptor returned from apr_dir_open
+ *
* @remark No ordering is guaranteed for the entries read.
+ * @c finfo->pool is set to the pool used to create @a thedir,
+ * and @c finfo->name is allocated from that pool.
*
* @note If @c APR_INCOMPLETE is returned all the fields in @a finfo may
* not be filled in, and you need to check the @c finfo->valid bitmask
* to verify that what you're looking for is there. When no more
* entries are available, APR_ENOENT is returned.
*
- * @warning Memory will be allocated in the pool passed to apr_dir_open;
- * use apr_dir_pread() and a temporary pool to restrict memory
+ * @warning Allocations will use the directory pool; use
+ * apr_dir_pread() and a temporary pool to restrict memory
* consumption for a large directory.
*/
APR_DECLARE(apr_status_t) apr_dir_read(apr_finfo_t *finfo, apr_int32_t wanted,
@@ -278,7 +281,10 @@ APR_DECLARE(apr_status_t) apr_dir_read(apr_finfo_t *finfo, apr_int32_t wanted,
values
* @param thedir the directory descriptor returned from apr_dir_open
* @param pool the pool to use for allocations
- * @remark No ordering is guaranteed for the entries read.
+
+ * @remark No ordering is guaranteed for the entries read.
+ * @remark @c finfo->pool is set to @a pool, and @c finfo->name is
+ * allocated from that pool.
*
* @note If @c APR_INCOMPLETE is returned all the fields in @a finfo may
* not be filled in, and you need to check the @c finfo->valid bitmask
diff --git a/test/testdir.c b/test/testdir.c
index bb3399cbf..a9f9e5275 100644
--- a/test/testdir.c
+++ b/test/testdir.c
@@ -21,6 +21,7 @@
#include "apr_file_info.h"
#include "apr_errno.h"
#include "apr_general.h"
+#include "apr_strings.h"
#include "apr_lib.h"
#include "apr_thread_proc.h"
#include "testutil.h"
@@ -460,6 +461,36 @@ static void test_pread(abts_case *tc, void *data)
}
#endif
+/* Ensure that apr_dir_read() doesn't have side-effects, because
+ * finfo->name points to a static buffer inside the apr_dir_t */
+static void test_read_side_effects(abts_case *tc, void *data)
+{
+ apr_dir_t *dir;
+ apr_finfo_t f1;
+ apr_finfo_t f2;
+ char name[APR_PATH_MAX], fname[APR_PATH_MAX];
+
+ APR_ASSERT_SUCCESS(tc, "apr_dir_open failed", apr_dir_open(&dir, "data", p));
+
+ APR_ASSERT_SUCCESS(tc, "apr_dir_read failed",
+ apr_dir_read(&f1, APR_FINFO_DIRENT, dir));
+
+ if (f1.name)
+ apr_cpystrn(name, f1.name, sizeof name);
+ if (f1.fname)
+ apr_cpystrn(fname, f1.fname, sizeof fname);
+
+ APR_ASSERT_SUCCESS(tc, "second apr_dir_read failed",
+ apr_dir_read(&f2, APR_FINFO_DIRENT, dir));
+
+ if (f1.name)
+ ABTS_STR_EQUAL(tc, name, f1.name);
+ if (f1.fname)
+ ABTS_STR_EQUAL(tc, fname, f1.fname);
+
+ APR_ASSERT_SUCCESS(tc, "apr_dir_close failed", apr_dir_close(dir));
+}
+
abts_suite *testdir(abts_suite *suite)
{
suite = ADD_SUITE(suite)
@@ -484,6 +515,7 @@ abts_suite *testdir(abts_suite *suite)
#if APR_POOL_DEBUG
abts_run_test(suite, test_pread, NULL);
#endif
+ abts_run_test(suite, test_read_side_effects, NULL);
return suite;
}