diff options
Diffstat (limited to 'src/backend/regex')
-rw-r--r-- | src/backend/regex/regc_lex.c | 9 | ||||
-rw-r--r-- | src/backend/regex/regc_locale.c | 54 | ||||
-rw-r--r-- | src/backend/regex/regcomp.c | 2 |
3 files changed, 48 insertions, 17 deletions
diff --git a/src/backend/regex/regc_lex.c b/src/backend/regex/regc_lex.c index 6f2c0cb3eb4..00da05571af 100644 --- a/src/backend/regex/regc_lex.c +++ b/src/backend/regex/regc_lex.c @@ -792,13 +792,13 @@ lexescape(struct vars * v) break; case CHR('u'): c = lexdigits(v, 16, 4, 4); - if (ISERR()) + if (ISERR() || c < CHR_MIN || c > CHR_MAX) FAILW(REG_EESCAPE); RETV(PLAIN, c); break; case CHR('U'): c = lexdigits(v, 16, 8, 8); - if (ISERR()) + if (ISERR() || c < CHR_MIN || c > CHR_MAX) FAILW(REG_EESCAPE); RETV(PLAIN, c); break; @@ -816,7 +816,7 @@ lexescape(struct vars * v) case CHR('x'): NOTE(REG_UUNPORT); c = lexdigits(v, 16, 1, 255); /* REs >255 long outside spec */ - if (ISERR()) + if (ISERR() || c < CHR_MIN || c > CHR_MAX) FAILW(REG_EESCAPE); RETV(PLAIN, c); break; @@ -872,6 +872,9 @@ lexescape(struct vars * v) /* * lexdigits - slurp up digits and return chr value + * + * This does not account for overflow; callers should range-check the result + * if maxlen is large enough to make that possible. */ static chr /* chr value; errors signalled via ERR */ lexdigits(struct vars * v, diff --git a/src/backend/regex/regc_locale.c b/src/backend/regex/regc_locale.c index e7bbb50ef46..4fe62921e3b 100644 --- a/src/backend/regex/regc_locale.c +++ b/src/backend/regex/regc_locale.c @@ -408,8 +408,7 @@ range(struct vars * v, /* context */ int nchrs; struct cvec *cv; celt c, - lc, - uc; + cc; if (a != b && !before(a, b)) { @@ -427,24 +426,51 @@ range(struct vars * v, /* context */ /* * When case-independent, it's hard to decide when cvec ranges are usable, - * so for now at least, we won't try. We allocate enough space for two - * case variants plus a little extra for the two title case variants. + * so for now at least, we won't try. We use a range for the originally + * specified chrs and then add on any case-equivalents that are outside + * that range as individual chrs. + * + * To ensure sane behavior if someone specifies a very large range, limit + * the allocation size to 100000 chrs (arbitrary) and check for overrun + * inside the loop below. */ + nchrs = b - a + 1; + if (nchrs <= 0 || nchrs > 100000) + nchrs = 100000; - nchrs = (b - a + 1) * 2 + 4; - - cv = getcvec(v, nchrs, 0); + cv = getcvec(v, nchrs, 1); NOERRN(); + addrange(cv, a, b); for (c = a; c <= b; c++) { - addchr(cv, c); - lc = pg_wc_tolower((chr) c); - if (c != lc) - addchr(cv, lc); - uc = pg_wc_toupper((chr) c); - if (c != uc) - addchr(cv, uc); + cc = pg_wc_tolower((chr) c); + if (cc != c && + (before(cc, a) || before(b, cc))) + { + if (cv->nchrs >= cv->chrspace) + { + ERR(REG_ETOOBIG); + return NULL; + } + addchr(cv, cc); + } + cc = pg_wc_toupper((chr) c); + if (cc != c && + (before(cc, a) || before(b, cc))) + { + if (cv->nchrs >= cv->chrspace) + { + ERR(REG_ETOOBIG); + return NULL; + } + addchr(cv, cc); + } + if (CANCEL_REQUESTED(v->re)) + { + ERR(REG_CANCEL); + return NULL; + } } return cv; diff --git a/src/backend/regex/regcomp.c b/src/backend/regex/regcomp.c index 487b5dabb82..7ae9673a7d5 100644 --- a/src/backend/regex/regcomp.c +++ b/src/backend/regex/regcomp.c @@ -1586,6 +1586,7 @@ dovec(struct vars * v, { ch = *p; newarc(v->nfa, PLAIN, subcolor(v->cm, ch), lp, rp); + NOERR(); } /* and the ranges */ @@ -1595,6 +1596,7 @@ dovec(struct vars * v, to = *(p + 1); if (from <= to) subrange(v, from, to, lp, rp); + NOERR(); } } |