mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
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.
This commit is contained in:
@ -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)
|
|||||||
* 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)
|
|||||||
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)
|
||||||
|
Reference in New Issue
Block a user