diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2011-04-17 13:36:38 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2011-04-17 13:37:39 -0400 |
commit | 88dc6fa7a164c306d8a1295769edb818d8520a3f (patch) | |
tree | add8980eb2317b81f9adc9fa3edcbdfbf618f98c /src | |
parent | d2f60a3ab055fb61c8e1056a7c5652f1dec85e00 (diff) | |
download | postgresql-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.c | 12 |
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) |