mirror of
https://github.com/postgres/postgres.git
synced 2025-04-27 22:56:53 +03:00
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.
This commit is contained in:
parent
50c5770ecd
commit
2b70588571
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "catalog/pg_type.h"
|
#include "catalog/pg_type.h"
|
||||||
#include "tsearch/ts_locale.h"
|
#include "tsearch/ts_locale.h"
|
||||||
|
#include "utils/memutils.h"
|
||||||
|
|
||||||
|
|
||||||
PG_MODULE_MAGIC;
|
PG_MODULE_MAGIC;
|
||||||
@ -188,6 +189,18 @@ generate_trgm(char *str, int slen)
|
|||||||
char *bword,
|
char *bword,
|
||||||
*eword;
|
*eword;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Guard against possible overflow in the palloc requests below. (We
|
||||||
|
* don't worry about the additive constants, since palloc can detect
|
||||||
|
* requests that are a little above MaxAllocSize --- we just need to
|
||||||
|
* prevent integer overflow in the multiplications.)
|
||||||
|
*/
|
||||||
|
if ((Size) (slen / 2) >= (MaxAllocSize / (sizeof(trgm) * 3)) ||
|
||||||
|
(Size) slen >= (MaxAllocSize / pg_database_encoding_max_length()))
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
||||||
|
errmsg("out of memory")));
|
||||||
|
|
||||||
trg = (TRGM *) palloc(TRGMHDRSIZE + sizeof(trgm) * (slen / 2 + 1) *3);
|
trg = (TRGM *) palloc(TRGMHDRSIZE + sizeof(trgm) * (slen / 2 + 1) *3);
|
||||||
trg->flag = ARRKEY;
|
trg->flag = ARRKEY;
|
||||||
SET_VARSIZE(trg, TRGMHDRSIZE);
|
SET_VARSIZE(trg, TRGMHDRSIZE);
|
||||||
@ -197,7 +210,8 @@ generate_trgm(char *str, int slen)
|
|||||||
|
|
||||||
tptr = GETARR(trg);
|
tptr = GETARR(trg);
|
||||||
|
|
||||||
buf = palloc(sizeof(char) * (slen + 4));
|
/* Allocate a buffer for case-folded, blank-padded words */
|
||||||
|
buf = (char *) palloc(slen * pg_database_encoding_max_length() + 4);
|
||||||
|
|
||||||
if (LPADDING > 0)
|
if (LPADDING > 0)
|
||||||
{
|
{
|
||||||
@ -221,6 +235,7 @@ generate_trgm(char *str, int slen)
|
|||||||
#ifdef IGNORECASE
|
#ifdef IGNORECASE
|
||||||
pfree(bword);
|
pfree(bword);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
buf[LPADDING + bytelen] = ' ';
|
buf[LPADDING + bytelen] = ' ';
|
||||||
buf[LPADDING + bytelen + 1] = ' ';
|
buf[LPADDING + bytelen + 1] = ' ';
|
||||||
|
|
||||||
@ -236,7 +251,10 @@ generate_trgm(char *str, int slen)
|
|||||||
if ((len = tptr - GETARR(trg)) == 0)
|
if ((len = tptr - GETARR(trg)) == 0)
|
||||||
return trg;
|
return trg;
|
||||||
|
|
||||||
if (len > 0)
|
/*
|
||||||
|
* Make trigrams unique.
|
||||||
|
*/
|
||||||
|
if (len > 1)
|
||||||
{
|
{
|
||||||
qsort((void *) GETARR(trg), len, sizeof(trgm), comp_trgm);
|
qsort((void *) GETARR(trg), len, sizeof(trgm), comp_trgm);
|
||||||
len = unique_array(GETARR(trg), len);
|
len = unique_array(GETARR(trg), len);
|
||||||
@ -419,6 +437,18 @@ generate_wildcard_trgm(const char *str, int slen)
|
|||||||
bytelen;
|
bytelen;
|
||||||
const char *eword;
|
const char *eword;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Guard against possible overflow in the palloc requests below. (We
|
||||||
|
* don't worry about the additive constants, since palloc can detect
|
||||||
|
* requests that are a little above MaxAllocSize --- we just need to
|
||||||
|
* prevent integer overflow in the multiplications.)
|
||||||
|
*/
|
||||||
|
if ((Size) (slen / 2) >= (MaxAllocSize / (sizeof(trgm) * 3)) ||
|
||||||
|
(Size) slen >= (MaxAllocSize / pg_database_encoding_max_length()))
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
||||||
|
errmsg("out of memory")));
|
||||||
|
|
||||||
trg = (TRGM *) palloc(TRGMHDRSIZE + sizeof(trgm) * (slen / 2 + 1) *3);
|
trg = (TRGM *) palloc(TRGMHDRSIZE + sizeof(trgm) * (slen / 2 + 1) *3);
|
||||||
trg->flag = ARRKEY;
|
trg->flag = ARRKEY;
|
||||||
SET_VARSIZE(trg, TRGMHDRSIZE);
|
SET_VARSIZE(trg, TRGMHDRSIZE);
|
||||||
@ -428,6 +458,7 @@ generate_wildcard_trgm(const char *str, int slen)
|
|||||||
|
|
||||||
tptr = GETARR(trg);
|
tptr = GETARR(trg);
|
||||||
|
|
||||||
|
/* Allocate a buffer for blank-padded, but not yet case-folded, words */
|
||||||
buf = palloc(sizeof(char) * (slen + 4));
|
buf = palloc(sizeof(char) * (slen + 4));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -448,6 +479,7 @@ generate_wildcard_trgm(const char *str, int slen)
|
|||||||
* count trigrams
|
* count trigrams
|
||||||
*/
|
*/
|
||||||
tptr = make_trigrams(tptr, buf2, bytelen, charlen);
|
tptr = make_trigrams(tptr, buf2, bytelen, charlen);
|
||||||
|
|
||||||
#ifdef IGNORECASE
|
#ifdef IGNORECASE
|
||||||
pfree(buf2);
|
pfree(buf2);
|
||||||
#endif
|
#endif
|
||||||
@ -461,7 +493,7 @@ generate_wildcard_trgm(const char *str, int slen)
|
|||||||
/*
|
/*
|
||||||
* Make trigrams unique.
|
* Make trigrams unique.
|
||||||
*/
|
*/
|
||||||
if (len > 0)
|
if (len > 1)
|
||||||
{
|
{
|
||||||
qsort((void *) GETARR(trg), len, sizeof(trgm), comp_trgm);
|
qsort((void *) GETARR(trg), len, sizeof(trgm), comp_trgm);
|
||||||
len = unique_array(GETARR(trg), len);
|
len = unique_array(GETARR(trg), len);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user