Skip to content

Commit f261ad2

Browse files
committed
Fix possible buffer overrun in contrib/pg_trgm.
Allow for the possibility that folding a string to lower case makes it longer (due to replacing a character with a longer multibyte character). This doesn't change the number of trigrams that will be extracted, but it does affect the required size of an intermediate buffer in generate_trgm(). Per bug #8821 from Ufuk Kayserilioglu. Also install some checks that the input string length is not so large as to cause overflow in the calculations of palloc request sizes. Back-patch to all supported versions.
1 parent 6c3f040 commit f261ad2

File tree

1 file changed

+21
-3
lines changed

1 file changed

+21
-3
lines changed

contrib/pg_trgm/trgm_op.c

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
*/
44
#include "trgm.h"
55
#include <ctype.h>
6-
#include "utils/array.h"
76
#include "catalog/pg_type.h"
87
#include "tsearch/ts_locale.h"
8+
#include "utils/array.h"
9+
#include "utils/memutils.h"
910

1011
PG_MODULE_MAGIC;
1112

@@ -172,6 +173,18 @@ generate_trgm(char *str, int slen)
172173
char *bword,
173174
*eword;
174175

176+
/*
177+
* Guard against possible overflow in the palloc requests below. (We
178+
* don't worry about the additive constants, since palloc can detect
179+
* requests that are a little above MaxAllocSize --- we just need to
180+
* prevent integer overflow in the multiplications.)
181+
*/
182+
if ((Size) (slen / 2) >= (MaxAllocSize / (sizeof(trgm) * 3)) ||
183+
(Size) slen >= (MaxAllocSize / pg_database_encoding_max_length()))
184+
ereport(ERROR,
185+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
186+
errmsg("out of memory")));
187+
175188
trg = (TRGM *) palloc(TRGMHDRSIZE + sizeof(trgm) * (slen / 2 + 1) *3);
176189
trg->flag = ARRKEY;
177190
SET_VARSIZE(trg, TRGMHDRSIZE);
@@ -181,7 +194,8 @@ generate_trgm(char *str, int slen)
181194

182195
tptr = GETARR(trg);
183196

184-
buf = palloc(sizeof(char) * (slen + 4));
197+
/* Allocate a buffer for case-folded, blank-padded words */
198+
buf = (char *) palloc(slen * pg_database_encoding_max_length() + 4);
185199

186200
if (LPADDING > 0)
187201
{
@@ -205,6 +219,7 @@ generate_trgm(char *str, int slen)
205219
#ifdef IGNORECASE
206220
pfree(bword);
207221
#endif
222+
208223
buf[LPADDING + bytelen] = ' ';
209224
buf[LPADDING + bytelen + 1] = ' ';
210225

@@ -220,7 +235,10 @@ generate_trgm(char *str, int slen)
220235
if ((len = tptr - GETARR(trg)) == 0)
221236
return trg;
222237

223-
if (len > 0)
238+
/*
239+
* Make trigrams unique.
240+
*/
241+
if (len > 1)
224242
{
225243
qsort((void *) GETARR(trg), len, sizeof(trgm), comp_trgm);
226244
len = unique_array(GETARR(trg), len);

0 commit comments

Comments
 (0)