From 3d3c05c70fc7c1ce7794ebff55aa251a589de851 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 24 Aug 2022 13:01:40 -0400 Subject: [PATCH] Defend against stack overrun in a few more places. 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 --- src/backend/regex/regc_lex.c | 5 +++-- src/backend/tsearch/spell.c | 4 ++++ src/backend/utils/adt/geo_ops.c | 3 +++ src/backend/utils/adt/like_support.c | 4 ++++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/backend/regex/regc_lex.c b/src/backend/regex/regc_lex.c index 45727ffa01f..4780d79f097 100644 --- a/src/backend/regex/regc_lex.c +++ b/src/backend/regex/regc_lex.c @@ -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 */ @@ -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); diff --git a/src/backend/tsearch/spell.c b/src/backend/tsearch/spell.c index f07321b61df..edd2fbbd3a5 100644 --- a/src/backend/tsearch/spell.c +++ b/src/backend/tsearch/spell.c @@ -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" @@ -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); diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c index b79705f8b3f..535301a2180 100644 --- a/src/backend/utils/adt/geo_ops.c +++ b/src/backend/utils/adt/geo_ops.c @@ -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)]; diff --git a/src/backend/utils/adt/like_support.c b/src/backend/utils/adt/like_support.c index 65a57fc3c46..2d3aaaaf6bd 100644 --- a/src/backend/utils/adt/like_support.c +++ b/src/backend/utils/adt/like_support.c @@ -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" @@ -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] == '(')