Skip to content

Commit fc27b40

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 5143dfd commit fc27b40

File tree

1 file changed

+35
-3
lines changed

1 file changed

+35
-3
lines changed

contrib/pg_trgm/trgm_op.c

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include "catalog/pg_type.h"
1111
#include "tsearch/ts_locale.h"
12+
#include "utils/memutils.h"
1213
#include "utils/array.h"
1314

1415

@@ -192,6 +193,18 @@ generate_trgm(char *str, int slen)
192193
char *bword,
193194
*eword;
194195

196+
/*
197+
* Guard against possible overflow in the palloc requests below. (We
198+
* don't worry about the additive constants, since palloc can detect
199+
* requests that are a little above MaxAllocSize --- we just need to
200+
* prevent integer overflow in the multiplications.)
201+
*/
202+
if ((Size) (slen / 2) >= (MaxAllocSize / (sizeof(trgm) * 3)) ||
203+
(Size) slen >= (MaxAllocSize / pg_database_encoding_max_length()))
204+
ereport(ERROR,
205+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
206+
errmsg("out of memory")));
207+
195208
trg = (TRGM *) palloc(TRGMHDRSIZE + sizeof(trgm) * (slen / 2 + 1) *3);
196209
trg->flag = ARRKEY;
197210
SET_VARSIZE(trg, TRGMHDRSIZE);
@@ -201,7 +214,8 @@ generate_trgm(char *str, int slen)
201214

202215
tptr = GETARR(trg);
203216

204-
buf = palloc(sizeof(char) * (slen + 4));
217+
/* Allocate a buffer for case-folded, blank-padded words */
218+
buf = (char *) palloc(slen * pg_database_encoding_max_length() + 4);
205219

206220
if (LPADDING > 0)
207221
{
@@ -225,6 +239,7 @@ generate_trgm(char *str, int slen)
225239
#ifdef IGNORECASE
226240
pfree(bword);
227241
#endif
242+
228243
buf[LPADDING + bytelen] = ' ';
229244
buf[LPADDING + bytelen + 1] = ' ';
230245

@@ -240,7 +255,10 @@ generate_trgm(char *str, int slen)
240255
if ((len = tptr - GETARR(trg)) == 0)
241256
return trg;
242257

243-
if (len > 0)
258+
/*
259+
* Make trigrams unique.
260+
*/
261+
if (len > 1)
244262
{
245263
qsort((void *) GETARR(trg), len, sizeof(trgm), comp_trgm);
246264
len = unique_array(GETARR(trg), len);
@@ -423,6 +441,18 @@ generate_wildcard_trgm(const char *str, int slen)
423441
bytelen;
424442
const char *eword;
425443

444+
/*
445+
* Guard against possible overflow in the palloc requests below. (We
446+
* don't worry about the additive constants, since palloc can detect
447+
* requests that are a little above MaxAllocSize --- we just need to
448+
* prevent integer overflow in the multiplications.)
449+
*/
450+
if ((Size) (slen / 2) >= (MaxAllocSize / (sizeof(trgm) * 3)) ||
451+
(Size) slen >= (MaxAllocSize / pg_database_encoding_max_length()))
452+
ereport(ERROR,
453+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
454+
errmsg("out of memory")));
455+
426456
trg = (TRGM *) palloc(TRGMHDRSIZE + sizeof(trgm) * (slen / 2 + 1) *3);
427457
trg->flag = ARRKEY;
428458
SET_VARSIZE(trg, TRGMHDRSIZE);
@@ -432,6 +462,7 @@ generate_wildcard_trgm(const char *str, int slen)
432462

433463
tptr = GETARR(trg);
434464

465+
/* Allocate a buffer for blank-padded, but not yet case-folded, words */
435466
buf = palloc(sizeof(char) * (slen + 4));
436467

437468
/*
@@ -452,6 +483,7 @@ generate_wildcard_trgm(const char *str, int slen)
452483
* count trigrams
453484
*/
454485
tptr = make_trigrams(tptr, buf2, bytelen, charlen);
486+
455487
#ifdef IGNORECASE
456488
pfree(buf2);
457489
#endif
@@ -465,7 +497,7 @@ generate_wildcard_trgm(const char *str, int slen)
465497
/*
466498
* Make trigrams unique.
467499
*/
468-
if (len > 0)
500+
if (len > 1)
469501
{
470502
qsort((void *) GETARR(trg), len, sizeof(trgm), comp_trgm);
471503
len = unique_array(GETARR(trg), len);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy