8000 Preserve memory context of VarStringSortSupport buffers. · postgres/postgres@84f9691 · GitHub
[go: up one dir, main page]

Skip to content

Commit 84f9691

Browse files
committed
Preserve memory context of VarStringSortSupport buffers.
When enlarging the work buffers of a VarStringSortSupport object, varstrfastcmp_locale was careful to keep them in the ssup_cxt memory context; but varstr_abbrev_convert just used palloc(). The latter creates a hazard that the buffers could be freed out from under the VarStringSortSupport object, resulting in stomping on whatever gets allocated in that memory later. In practice, because we only use this code for ICU collations (cf. 3df9c37), the problem is confined to use of ICU collations. I believe it may have been unreachable before the introduction of incremental sort, too, as traditional sorting usually just uses one context for the duration of the sort. We could fix this by making the broken stanzas in varstr_abbrev_convert match the non-broken ones in varstrfastcmp_locale. However, it seems like a better idea to dodge the issue altogether by replacing the pfree-and-allocate-anew coding with repalloc, which automatically preserves the chunk's memory context. This fix does add a few cycles because repalloc will copy the chunk's content, which the existing coding assumes is useless. However, we don't expect that these buffer enlargement operations are performance-critical. Besides that, it's far from obvious that copying the buffer contents isn't required, since these stanzas make no effort to mark the buffers invalid by resetting last_returned, cache_blob, etc. That seems to be safe upon examination, but it's fragile and could easily get broken in future, which wouldn't get revealed in testing with short-to-moderate-size strings. Per bug #17584 from James Inform. Whether or not the issue is reachable in the older branches, this code has been broken on its own terms from its introduction, so patch all the way back. Discussion: https://postgr.es/m/17584-95c79b4a7d771f44@postgresql.org
1 parent b744e13 commit 84f9691

File tree

1 file changed

+6
-10
lines changed

1 file changed

+6
-10
lines changed

src/backend/utils/adt/varlena.c

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@ typedef struct
6262
char *buf1; /* 1st string, or abbreviation original string
6363
* buf */
6464
char *buf2; /* 2nd string, or abbreviation strxfrm() buf */
65-
int buflen1;
66-
int buflen2;
65+
int buflen1; /* Allocated length of buf1 */
66+
int buflen2; /* Allocated length of buf2 */
6767
int last_len1; /* Length of last buf1 string/strxfrm() input */
6868
int last_len2; /* Length of last buf2 string/strxfrm() blob */
6969
int last_returned; /* Last comparison result (cache) */
@@ -2117,15 +2117,13 @@ varstrfastcmp_locale(Datum x, Datum y, SortSupport ssup)
21172117

21182118
if (len1 >= sss->buflen1)
21192119
{
2120-
pfree(sss->buf1);
21212120
sss->buflen1 = Max(len1 + 1, Min(sss->buflen1 * 2, MaxAllocSize));
2122-
sss->buf1 = MemoryContextAlloc(ssup->ssup_cxt, sss->buflen1);
2121+
sss->buf1 = repalloc(sss->buf1, sss->buflen1);
21232122
}
21242123
if (len2 >= sss->buflen2)
21252124
{
2126-
pfree(sss->buf2);
21272125
sss->buflen2 = Max(len2 + 1, Min(sss->buflen2 * 2, MaxAllocSize));
2128-
sss->buf2 = MemoryContextAlloc(ssup->ssup_cxt, sss->buflen2);
2126+
sss->buf2 = repalloc(sss->buf2, sss->buflen2);
21292127
}
21302128

21312129
/*
@@ -2337,9 +2335,8 @@ varstr_abbrev_convert(Datum original, SortSupport ssup)
23372335
/* By convention, we use buffer 1 to store and NUL-terminate */
23382336
if (len >= sss->buflen1)
23392337
{
2340-
pfree(sss->buf1);
23412338
sss->buflen1 = Max(len + 1, Min(sss->buflen1 * 2, MaxAllocSize));
2342-
sss->buf1 = palloc(sss->buflen1);
2339+
sss->buf1 = repalloc(sss->buf1, sss->buflen1);
23432340
}
23442341

23452342
/* Might be able to reuse strxfrm() blob from last call */
@@ -2426,10 +2423,9 @@ varstr_abbrev_convert(Datum original, SortSupport ssup)
24262423
/*
24272424
* Grow buffer and retry.
24282425
*/
2429-
pfree(sss->buf2);
24302426
sss->buflen2 = Max(bsize + 1,
24312427
Min(sss->buflen2 * 2, MaxAllocSize));
2432-
sss->buf2 = palloc(sss->buflen2);
2428+
sss->buf2 = repalloc(sss->buf2, sss->buflen2);
24332429
}
24342430

24352431
/*

0 commit comments

Comments
 (0)
0