Defend against stack overrun in a few more places.
authorTom Lane <[email protected]>
Wed, 24 Aug 2022 17:01:40 +0000 (13:01 -0400)
committerTom Lane <[email protected]>
Wed, 24 Aug 2022 17:02:19 +0000 (13:02 -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 45727ffa01f719d64030a6aec2e1922c9e3a83e0..4780d79f097fc2b02331efe0f9c44ff1f40f6f94 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 f07321b61df23bee542cc55181037b499e133783..edd2fbbd3a5f17c0b2f9ac91a5940b0ad52d7d7e 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"
@@ -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);
index b79705f8b3f16fe47a848e4813e254d249d1330c..535301a218063c70cc36a7cff9e41927167148ae 100644 (file)
@@ -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)];
index 65a57fc3c461d615f7607ae9bc51f5690c6627d9..2d3aaaaf6bdee1adefebf187a65b0895c654a2c9 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"
@@ -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] == '(')