1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-03-03 14:52:21 +02:00

Fix issue when listing directories recursively with a filter.

While recursing and filtering, if the last entry in a directory was another directory containing entries then the parent list would get freed too early, causing a double free error or segfault.

Fix by ensuring that the completed list is at the top of the stack before freeing it. This will defer freeing parent lists until the contents of paths have been processed.
This commit is contained in:
David Steele 2022-09-15 12:00:44 -07:00 committed by GitHub
parent 08a44be4c3
commit c39c9f220e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 25 additions and 2 deletions

View File

@ -29,6 +29,19 @@
<p>Fix incorrect time expiration being used for non-default repos.</p>
</release-item>
<release-item>
<github-issue id="1870"/>
<github-pull-request id="1871"/>
<release-item-contributor-list>
<release-item-ideator id="efremov.egor"/>
<release-item-contributor id="david.steele"/>
<release-item-reviewer id="stephen.frost"/>
</release-item-contributor-list>
<p>Fix issue when listing directories recursively with a filter.</p>
</release-item>
</release-bug-list>
<release-feature-list>

View File

@ -244,7 +244,11 @@ storageItrMore(StorageIterator *const this)
}
// If no more info then free the list. This check is required because we may break out of the above loop early.
if (listInfo->listIdx >= storageLstSize(listInfo->list))
//
// Only free when the list is at the top of the stack. It is possible that this is the last entry in the current list but
// it is a path that must be checked for entries. In that case the path entries will end up at the top of the stack so we'll
// need to wait to free the list containing the path until the path entries have been processed.
if (listInfo->listIdx >= storageLstSize(listInfo->list) && listInfo == *(StorageIteratorInfo **)lstGetLast(this->stack))
{
objFree(listInfo);
lstRemoveLast(this->stack);

View File

@ -444,6 +444,8 @@ testRun(void)
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("path - recurse asc");
// Create a path with a subpath that will always be last to make sure lists are not freed too early in the iterator
storagePathCreateP(storageTest, STRDEF("pg/zzz/yyy"), .mode = 0700);
TEST_STORAGE_LIST(
storageTest, "pg",
@ -452,7 +454,9 @@ testRun(void)
"link> {d=../file}\n"
"path/\n"
"path/file {s=8, t=1656434296}\n"
"pipe*\n",
"pipe*\n"
"zzz/\n"
"zzz/yyy/\n",
.level = storageInfoLevelBasic, .includeDot = true);
// -------------------------------------------------------------------------------------------------------------------------
@ -462,6 +466,8 @@ testRun(void)
TEST_STORAGE_LIST(
storageTest, "pg",
"zzz/yyy/\n"
"zzz/\n"
"pipe*\n"
"path/file {s=8, t=1656434296}\n"
"path/\n"