make-ResourceOwnerReleaseAll-safer.patch
text/x-diff
Filename: make-ResourceOwnerReleaseAll-safer.patch
Type: text/x-diff
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/utils/resowner/resowner.c | 15 | 5 |
diff --git a/src/backend/utils/resowner/resowner.c b/src/backend/utils/resowner/resowner.c
index 06e1121c5ff..03d2f5a0334 100644
--- a/src/backend/utils/resowner/resowner.c
+++ b/src/backend/utils/resowner/resowner.c
@@ -347,6 +347,7 @@ ResourceOwnerReleaseAll(ResourceOwner owner, ResourceReleasePhase phase,
{
ResourceElem *items;
uint32 nitems;
+ bool using_arr;
/*
* ResourceOwnerSort must've been called already. All the resources are
@@ -358,12 +359,14 @@ ResourceOwnerReleaseAll(ResourceOwner owner, ResourceReleasePhase phase,
{
items = owner->arr;
nitems = owner->narr;
+ using_arr = true;
}
else
{
Assert(owner->narr == 0);
items = owner->hash;
nitems = owner->nhash;
+ using_arr = false;
}
/*
@@ -392,13 +395,20 @@ ResourceOwnerReleaseAll(ResourceOwner owner, ResourceReleasePhase phase,
elog(WARNING, "resource was not closed: %s", res_str);
pfree(res_str);
}
- kind->ReleaseResource(value);
+
+ /*
+ * Update stored count to forget the item before calling its
+ * ReleaseResource method. This avoids double-free crashes in case an
+ * error gets thrown within ReleaseResource.
+ */
nitems--;
+ if (using_arr)
+ owner->narr = nitems;
+ else
+ owner->nhash = nitems;
+
+ kind->ReleaseResource(value);
}
- if (owner->nhash == 0)
- owner->narr = nitems;
- else
- owner->nhash = nitems;
}