Defend against stack overrun in a few more places.
authorTom Lane
Wed, 24 Aug 2022 17:01:40 +0000 (13:01 -0400)
committerTom Lane
Wed, 24 Aug 2022 17:01:40 +0000 (13:01 -0400)
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
src/backend/tsearch/spell.c
src/backend/utils/adt/geo_ops.c
src/backend/utils/adt/like_support.c

index 16664531641c8f541ef8f4dfcf33802c5fc3baa8..d573032db67a610b3bd95191ad14ed79f3a8bec5 100644 (file)
@@ -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);
index 756fc859acf30966ac73a457c7949fc06ee5b4e9..d42e5fb3c2c3bae8fed39aa4c345eccc2f50e512 100644 (file)
@@ -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);
index a7db7839588817175231c3b8e62703bc94e37457..3b9e68ffd46882808434d6afab632142f2681cd0 100644 (file)
@@ -3907,6 +3907,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)];
index b9144e0abb2a074e3b3d27af8159ad4847d2da3c..ed4d6a8dc67291a9694266f5db164bbd746547bf 100644 (file)
@@ -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"
@@ -1338,6 +1339,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] == '(')