aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2011-04-17 13:36:38 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2011-04-17 13:37:39 -0400
commit88dc6fa7a164c306d8a1295769edb818d8520a3f (patch)
treeadd8980eb2317b81f9adc9fa3edcbdfbf618f98c /src
parentd2f60a3ab055fb61c8e1056a7c5652f1dec85e00 (diff)
downloadpostgresql-88dc6fa7a164c306d8a1295769edb818d8520a3f.tar.gz
postgresql-88dc6fa7a164c306d8a1295769edb818d8520a3f.zip
foreach() and list_delete() don't mix.
Fix crash when releasing duplicate entries in the encoding conversion cache list, caused by releasing the current entry of the list being chased by foreach(). We have a standard idiom for handling such cases, but this loop wasn't using it. This got broken in my recent rewrite of GUC assign hooks. Not sure how I missed this when testing the modified code, but I did. Per report from Peter.
Diffstat (limited to 'src')
-rw-r--r--src/backend/utils/mb/mbutils.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/src/backend/utils/mb/mbutils.c b/src/backend/utils/mb/mbutils.c
index 234bb0cf6e8..3cb7ce3269d 100644
--- a/src/backend/utils/mb/mbutils.c
+++ b/src/backend/utils/mb/mbutils.c
@@ -189,6 +189,8 @@ SetClientEncoding(int encoding)
int current_server_encoding;
bool found;
ListCell *lc;
+ ListCell *prev;
+ ListCell *next;
if (!PG_VALID_FE_ENCODING(encoding))
return -1;
@@ -222,10 +224,13 @@ SetClientEncoding(int encoding)
* leak memory.
*/
found = false;
- foreach(lc, ConvProcList)
+ prev = NULL;
+ for (lc = list_head(ConvProcList); lc; lc = next)
{
ConvProcInfo *convinfo = (ConvProcInfo *) lfirst(lc);
+ next = lnext(lc);
+
if (convinfo->s_encoding == current_server_encoding &&
convinfo->c_encoding == encoding)
{
@@ -240,10 +245,13 @@ SetClientEncoding(int encoding)
else
{
/* Duplicate entry, release it */
- ConvProcList = list_delete_ptr(ConvProcList, convinfo);
+ ConvProcList = list_delete_cell(ConvProcList, lc, prev);
pfree(convinfo);
+ continue; /* prev mustn't advance */
}
}
+
+ prev = lc;
}
if (found)