Skip to content

Commit

Permalink
Defend against stack overrun in a few more places.
Browse files Browse the repository at this point in the history
SplitToVariants() in the ispell code, lseg_inside_poly() in geo_ops.c,
and regex_selectivity_sub() in selectivity estimation could recurse
until stack overflow; fix by adding check_stack_depth() calls.
So could next() in the regex compiler, but that case is better fixed by
converting its tail recursion to a loop.  (We probably get better code
that way too, since next() can now be inlined into its sole caller.)

There remains a reachable stack overrun in the Turkish stemmer, but
we'll need some advice from the Snowball people about how to fix that.

Per report from Egor Chindyaskin and Alexander Lakhin.  These mistakes
are old, so back-patch to all supported branches.

Richard Guo and Tom Lane

Discussion: https://postgr.es/m/1661334672.728714027@f473.i.mail.ru
  • Loading branch information
tglsfdc committed Aug 24, 2022
1 parent a73d6c8 commit f25bed3
Show file tree
Hide file tree
Showing 4 changed files with 14 additions and 2 deletions.
5 changes: 3 additions & 2 deletions src/backend/regex/regc_lex.c
Expand Up @@ -201,6 +201,8 @@ next(struct vars *v)
{
chr c;

next_restart: /* loop here after eating a comment */

/* errors yield an infinite sequence of failures */
if (ISERR())
return 0; /* the error has set nexttype to EOS */
Expand Down Expand Up @@ -493,8 +495,7 @@ next(struct vars *v)
if (!ATEOS())
v->now++;
assert(v->nexttype == v->lasttype);
return next(v);
break;
goto next_restart;
case CHR('='): /* positive lookahead */
NOTE(REG_ULOOKAROUND);
RETV(LACON, LATYPE_AHEAD_POS);
Expand Down
4 changes: 4 additions & 0 deletions src/backend/tsearch/spell.c
Expand Up @@ -63,6 +63,7 @@
#include "postgres.h"

#include "catalog/pg_collation.h"
#include "miscadmin.h"
#include "tsearch/dicts/spell.h"
#include "tsearch/ts_locale.h"
#include "utils/memutils.h"
Expand Down Expand Up @@ -2400,6 +2401,9 @@ SplitToVariants(IspellDict *Conf, SPNode *snode, SplitVar *orig, char *word, int
char *notprobed;
int compoundflag = 0;

/* since this function recurses, it could be driven to stack overflow */
check_stack_depth();

notprobed = (char *) palloc(wordlen);
memset(notprobed, 1, wordlen);
var = CopyVar(orig, 1);
Expand Down
3 changes: 3 additions & 0 deletions src/backend/utils/adt/geo_ops.c
Expand Up @@ -3833,6 +3833,9 @@ lseg_inside_poly(Point *a, Point *b, POLYGON *poly, int start)
bool res = true,
intersection = false;

/* since this function recurses, it could be driven to stack overflow */
check_stack_depth();

t.p[0] = *a;
t.p[1] = *b;
s.p[0] = poly->p[(start == 0) ? (poly->npts - 1) : (start - 1)];
Expand Down
4 changes: 4 additions & 0 deletions src/backend/utils/adt/like_support.c
Expand Up @@ -44,6 +44,7 @@
#include "catalog/pg_statistic.h"
#include "catalog/pg_type.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "nodes/supportnodes.h"
Expand Down Expand Up @@ -1364,6 +1365,9 @@ regex_selectivity_sub(const char *patt, int pattlen, bool case_insensitive)
int paren_pos = 0; /* dummy init to keep compiler quiet */
int pos;

/* since this function recurses, it could be driven to stack overflow */
check_stack_depth();

for (pos = 0; pos < pattlen; pos++)
{
if (patt[pos] == '(')
Expand Down

0 comments on commit f25bed3

Please sign in to comment.