Commit 88dc6fa7 authored by Tom Lane's avatar Tom Lane

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.
parent d2f60a3a
...@@ -189,6 +189,8 @@ SetClientEncoding(int encoding) ...@@ -189,6 +189,8 @@ SetClientEncoding(int encoding)
int current_server_encoding; int current_server_encoding;
bool found; bool found;
ListCell *lc; ListCell *lc;
ListCell *prev;
ListCell *next;
if (!PG_VALID_FE_ENCODING(encoding)) if (!PG_VALID_FE_ENCODING(encoding))
return -1; return -1;
...@@ -222,10 +224,13 @@ SetClientEncoding(int encoding) ...@@ -222,10 +224,13 @@ SetClientEncoding(int encoding)
* leak memory. * leak memory.
*/ */
found = false; found = false;
foreach(lc, ConvProcList) prev = NULL;
for (lc = list_head(ConvProcList); lc; lc = next)
{ {
ConvProcInfo *convinfo = (ConvProcInfo *) lfirst(lc); ConvProcInfo *convinfo = (ConvProcInfo *) lfirst(lc);
next = lnext(lc);
if (convinfo->s_encoding == current_server_encoding && if (convinfo->s_encoding == current_server_encoding &&
convinfo->c_encoding == encoding) convinfo->c_encoding == encoding)
{ {
...@@ -240,10 +245,13 @@ SetClientEncoding(int encoding) ...@@ -240,10 +245,13 @@ SetClientEncoding(int encoding)
else else
{ {
/* Duplicate entry, release it */ /* Duplicate entry, release it */
ConvProcList = list_delete_ptr(ConvProcList, convinfo); ConvProcList = list_delete_cell(ConvProcList, lc, prev);
pfree(convinfo); pfree(convinfo);
continue; /* prev mustn't advance */
} }
} }
prev = lc;
} }
if (found) if (found)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment