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 7673dab76f486791643c1a31de7a2cc6773d8f7f..826203e35d2525e2c5342e761f32a97eb3b22fd6 100644 (file)
@@ -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);
index ebc89604ac2071e333400b01516aacddae413764..961eb2709ca06147ccc662be530f0c1253d56672 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 9484dbc22737abfb098203f4054816d4f62fee06..bfd9ff6a36cc9af8be983a82e7a3d208bf4e10e8 100644 (file)
@@ -3919,6 +3919,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 241e6f0f598ae2f5ddd12bb5e804c594389c89dd..cba2d1376f0e1723f9230cd17e4e0849fbb321bd 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] == '(')