aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2022-08-24 13:01:40 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2022-08-24 13:01:40 -0400
commit599a487b093acb23ae1da7fe29eb0b6a4c26cc2c (patch)
tree6f23dfb149f68aad6e91d86b134dc61ef1267a70 /src
parent7951e0d7af98fabec9e9146b409b4c5636932d66 (diff)
downloadpostgresql-599a487b093acb23ae1da7fe29eb0b6a4c26cc2c.tar.gz
postgresql-599a487b093acb23ae1da7fe29eb0b6a4c26cc2c.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/backend/regex/regc_lex.c5
-rw-r--r--src/backend/tsearch/spell.c4
-rw-r--r--src/backend/utils/adt/geo_ops.c3
-rw-r--r--src/backend/utils/adt/like_support.c4
4 files changed, 14 insertions, 2 deletions
diff --git a/src/backend/regex/regc_lex.c b/src/backend/regex/regc_lex.c
index 16664531641..d573032db67 100644
--- a/src/backend/regex/regc_lex.c
+++ b/src/backend/regex/regc_lex.c
@@ -278,6 +278,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 */
@@ -595,8 +597,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 0eb68a6e2e1..013b2ef8b6c 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"
@@ -2399,6 +2400,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 cb8f723e66b..11b6ee4bc9e 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -3791,6 +3791,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 822a234df36..fe88415d065 100644
--- a/src/backend/utils/adt/like_support.c
+++ b/src/backend/utils/adt/like_support.c
@@ -43,6 +43,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"
@@ -1320,6 +1321,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] == '(')