--- httpd-2.2.21.orig/modules/dav/fs/repos.c 2012-01-30 16:01:53.000000000 +0100 +++ httpd-2.2.21.orig/modules/dav/fs/repos.c 2012-01-30 16:02:42.000000000 +0100 @@ -1431,6 +1431,8 @@ static dav_error * dav_fs_walker(dav_fs_ apr_finfo_t dirent; apr_dir_t *dirp; apr_pool_t *subpool; + apr_pool_t *save_res1_pool; + apr_pool_t *save_res2_pool; /* ensure the context is prepared properly, then call the func */ err = (*params->func)(&fsctx->wres, @@ -1472,7 +1474,15 @@ static dav_error * dav_fs_walker(dav_fs_ /* ### need a better error */ return dav_new_error(pool, HTTP_NOT_FOUND, 0, NULL); } + + /* do not share resource pools with childs, so that we can reuse memory */ apr_pool_create(&subpool, pool); + save_res1_pool = fsctx->res1.pool; + save_res2_pool = fsctx->res2.pool; + fsctx->res1.pool = subpool; + if (fsctx->res2.pool) + fsctx->res2.pool = subpool; + while ((apr_dir_read(&dirent, APR_FINFO_DIRENT, dirp)) == APR_SUCCESS) { apr_size_t len; apr_status_t status; @@ -1561,6 +1571,10 @@ static dav_error * dav_fs_walker(dav_fs_ /* ### don't always want to quit on error from single child */ if ((err = dav_fs_walker(fsctx, depth - 1)) != NULL) { /* ### maybe add a higher-level description? */ + /* ### any returned error would have to be deep-copied + to pool since it may have been allocated in a + subpool that will be destroyed before the + request terminates. */ break; } @@ -1578,12 +1592,23 @@ static dav_error * dav_fs_walker(dav_fs_ /* ### check the return value of this? */ apr_dir_close(dirp); - apr_pool_destroy(subpool); - subpool = NULL; + + /* restore parent resource pools and get rid of children's pool */ + fsctx->res1.pool = save_res1_pool; + fsctx->res2.pool = save_res2_pool; + + /* If an error occurs the subpool is not destroyed since the error + * may have been allocated from it, so the error allocation will + * have the same lifetime as the main pool. */ + /* ### It would be cleaner to deep-copy the error objet to the + * main pool as suggested above.*/ if (err != NULL) return err; + apr_pool_destroy(subpool); + subpool = NULL; + if (params->walk_type & DAV_WALKTYPE_LOCKNULL) { apr_size_t offset = 0;