]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Defend against stack overrun in a few more places.
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 24 Aug 2022 17:01:40 +0000 (13:01 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
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 0eb68a6e2e1a352e3148dc6e9180275be84b0d91..013b2ef8b6cfab6d5871aa9962819af525af7a3e 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 cb8f723e66be76e955b20ea9823d7e68a9315fd4..11b6ee4bc9e3f80d6341ddd6b051225358d000fe 100644 (file)
@@ -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)];
index 822a234df364a387399a84d4b7a40d044e3a8d30..fe88415d06559d6829d177ed81ebab1e8b9f13c8 100644 (file)
@@ -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] == '(')