683572
From fd30a7c49a661aecfb361045646da264cdadea8f Mon Sep 17 00:00:00 2001
683572
From: Karl Williamson <khw@cpan.org>
683572
Date: Fri, 23 Aug 2019 12:40:24 -0600
683572
Subject: [PATCH] PATCH: [perl #134329] Use after free in regcomp.c
683572
MIME-Version: 1.0
683572
Content-Type: text/plain; charset=UTF-8
683572
Content-Transfer-Encoding: 8bit
683572
683572
A compiled regex is composed of nodes, forming a linked list, with
683572
normally a maximum of 16 bits used to specify the offset of the next
683572
link.  For patterns that require more space than this, the nodes that
683572
jump around are replaced with ones that have wider offsets.  Most nodes
683572
are unaffected, as they just contain the offset of the next node, and
683572
that number is always small.  The jump nodes are the ones affected.
683572
683572
When compiling a pattern, the 16 bit mechanism is used, until it
683572
overflows, at which point the pattern is recompiled with the long jumps
683572
instead.
683572
683572
When I rewrote the compiler last year to make it generally one pass, I
683572
noticed a lot of the cases where a node was added didn't check if the
683572
result overflowed (the function that does this returns FALSE in that
683572
case).  I presumed the prior authors knew better, and did not change
683572
things, except to put in a bogus value in the link (offset) field that
683572
should cause a crash if it were used.  That's what's happening in this
683572
ticket.
683572
683572
But seeing this example, it's clear that the return value should be
683572
checked every time, because you can reach the limit at any time.  This
683572
commit changes to do that, and to require the function's return value to
683572
not be ignored, to guard against future changes.
683572
683572
My guess is that the reason it generally worked when there were multiple
683572
passes is that the first pass didn't do anything except count space, and
683572
that at some point before the end of the pass the return value did get
683572
checked, so by the time the nodes were allocated for real, it knew
683572
enough to use the long jumps.
683572
683572
Petr Písař: Ported to 5.30.0 from
683572
3b2e5620ed4a6b341f97ffd1d4b6466cc2c4bc5b.
683572
683572
Signed-off-by: Petr Písař <ppisar@redhat.com>
683572
---
683572
 MANIFEST                 |   1 +
683572
 embed.fnc                |   4 +-
683572
 proto.h                  |   8 ++-
683572
 regcomp.c                | 109 ++++++++++++++++++++++++++++-----------
683572
 t/re/bigfuzzy_not_utf8.t | Bin 0 -> 36399 bytes
683572
 5 files changed, 88 insertions(+), 34 deletions(-)
683572
 create mode 100644 t/re/bigfuzzy_not_utf8.t
683572
683572
diff --git a/MANIFEST b/MANIFEST
683572
index 10e2cc0..cc24cd7 100644
683572
--- a/MANIFEST
683572
+++ b/MANIFEST
683572
@@ -5839,6 +5839,7 @@ t/porting/test_bootstrap.t	Test that the instructions for test bootstrapping are
683572
 t/porting/utils.t		Check that utility scripts still compile
683572
 t/re/alpha_assertions.t		See if things like '(*postive_lookahed:...) work properly
683572
 t/re/anyof.t			See if bracketed char classes [...] compile properly
683572
+t/re/bigfuzzy_not_utf8.t	Big and ugly tests not storable as UTF-8
683572
 t/re/charset.t			See if regex modifiers like /d, /u work properly
683572
 t/re/fold_grind.pl		Core file to see if regex case folding works properly
683572
 t/re/fold_grind_8.t		Wrapper for fold_grind.pl for /l testing with a UTF-8 locale
683572
diff --git a/embed.fnc b/embed.fnc
683572
index c977d39..c2c5f16 100644
683572
--- a/embed.fnc
683572
+++ b/embed.fnc
683572
@@ -2427,7 +2427,7 @@ Es	|void	|reginsert	|NN RExC_state_t *pRExC_state \
683572
 				|const U8 op				    \
683572
 				|const regnode_offset operand		    \
683572
 				|const U32 depth
683572
-Es	|bool	|regtail	|NN RExC_state_t * pRExC_state		    \
683572
+EsR	|bool	|regtail	|NN RExC_state_t * pRExC_state		    \
683572
 				|NN const regnode_offset p		    \
683572
 				|NN const regnode_offset val		    \
683572
 				|const U32 depth
683572
@@ -2561,7 +2561,7 @@ Es	|void	|dump_trie_interim_list|NN const struct _reg_trie_data *trie\
683572
 Es	|void	|dump_trie_interim_table|NN const struct _reg_trie_data *trie\
683572
 				|NULLOK HV* widecharmap|NN AV *revcharmap\
683572
 				|U32 next_alloc|U32 depth
683572
-Es	|bool	|regtail_study	|NN RExC_state_t *pRExC_state \
683572
+EsR	|bool	|regtail_study	|NN RExC_state_t *pRExC_state \
683572
 				|NN regnode_offset p|NN const regnode_offset val|U32 depth
683572
 #  endif
683572
 #endif
683572
diff --git a/proto.h b/proto.h
683572
index e0ea55b..2ef7ce2 100644
683572
--- a/proto.h
683572
+++ b/proto.h
683572
@@ -4457,9 +4457,11 @@ PERL_CALLCONV int	Perl_re_indentf(pTHX_ const char *fmt, U32 depth, ...);
683572
 	assert(fmt)
683572
 STATIC void	S_regdump_extflags(pTHX_ const char *lead, const U32 flags);
683572
 STATIC void	S_regdump_intflags(pTHX_ const char *lead, const U32 flags);
683572
-STATIC bool	S_regtail_study(pTHX_ RExC_state_t *pRExC_state, regnode_offset p, const regnode_offset val, U32 depth);
683572
+STATIC bool	S_regtail_study(pTHX_ RExC_state_t *pRExC_state, regnode_offset p, const regnode_offset val, U32 depth)
683572
+			__attribute__warn_unused_result__;
683572
 #define PERL_ARGS_ASSERT_REGTAIL_STUDY	\
683572
 	assert(pRExC_state); assert(p); assert(val)
683572
+
683572
 #  endif
683572
 #  if defined(PERL_IN_REGEXEC_C)
683572
 STATIC void	S_debug_start_match(pTHX_ const REGEXP *prog, const bool do_utf8, const char *start, const char *end, const char *blurb);
683572
@@ -5599,9 +5601,11 @@ STATIC regnode_offset	S_regnode_guts(pTHX_ RExC_state_t *pRExC_state, const U8 o
683572
 STATIC regnode_offset	S_regpiece(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth);
683572
 #define PERL_ARGS_ASSERT_REGPIECE	\
683572
 	assert(pRExC_state); assert(flagp)
683572
-STATIC bool	S_regtail(pTHX_ RExC_state_t * pRExC_state, const regnode_offset p, const regnode_offset val, const U32 depth);
683572
+STATIC bool	S_regtail(pTHX_ RExC_state_t * pRExC_state, const regnode_offset p, const regnode_offset val, const U32 depth)
683572
+			__attribute__warn_unused_result__;
683572
 #define PERL_ARGS_ASSERT_REGTAIL	\
683572
 	assert(pRExC_state); assert(p); assert(val)
683572
+
683572
 STATIC void	S_scan_commit(pTHX_ const RExC_state_t *pRExC_state, struct scan_data_t *data, SSize_t *minlenp, int is_inf);
683572
 #define PERL_ARGS_ASSERT_SCAN_COMMIT	\
683572
 	assert(pRExC_state); assert(data); assert(minlenp)
683572
diff --git a/regcomp.c b/regcomp.c
683572
index dfc22bc..b93fbe7 100644
683572
--- a/regcomp.c
683572
+++ b/regcomp.c
683572
@@ -11307,10 +11307,15 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp, U32 depth)
683572
                         return 0;
683572
                     }
683572
 
683572
-                    REGTAIL(pRExC_state, ret, atomic);
683572
+                    if (! REGTAIL(pRExC_state, ret, atomic)) {
683572
+                        REQUIRE_BRANCHJ(flagp, 0);
683572
+                    }
683572
 
683572
-                    REGTAIL(pRExC_state, atomic,
683572
-                           reg_node(pRExC_state, SRCLOSE));
683572
+                    if (! REGTAIL(pRExC_state, atomic, reg_node(pRExC_state,
683572
+                                                                SRCLOSE)))
683572
+                    {
683572
+                        REQUIRE_BRANCHJ(flagp, 0);
683572
+                    }
683572
 
683572
                     RExC_in_script_run = 0;
683572
                     return ret;
683572
@@ -11769,7 +11774,9 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp, U32 depth)
683572
                                        RExC_flags & RXf_PMf_COMPILETIME
683572
                                       );
683572
                     FLAGS(REGNODE_p(ret)) = 2;
683572
-                    REGTAIL(pRExC_state, ret, eval);
683572
+                    if (! REGTAIL(pRExC_state, ret, eval)) {
683572
+                        REQUIRE_BRANCHJ(flagp, 0);
683572
+                    }
683572
                     /* deal with the length of this later - MJD */
683572
 		    return ret;
683572
 		}
683572
@@ -11822,7 +11829,9 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp, U32 depth)
683572
 
683572
                     tail = reg(pRExC_state, 1, &flag, depth+1);
683572
                     RETURN_FAIL_ON_RESTART(flag, flagp);
683572
-                    REGTAIL(pRExC_state, ret, tail);
683572
+                    if (! REGTAIL(pRExC_state, ret, tail)) {
683572
+                        REQUIRE_BRANCHJ(flagp, 0);
683572
+                    }
683572
                     goto insert_if;
683572
                 }
683572
 		else if (   RExC_parse[0] == '<'     /* (?(<NAME>)...) */
683572
@@ -11914,15 +11923,22 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp, U32 depth)
683572
 		    }
683572
 		    nextchar(pRExC_state);
683572
 		  insert_if:
683572
-                    REGTAIL(pRExC_state, ret, reganode(pRExC_state, IFTHEN, 0));
683572
+                    if (! REGTAIL(pRExC_state, ret, reganode(pRExC_state,
683572
+                                                             IFTHEN, 0)))
683572
+                    {
683572
+                        REQUIRE_BRANCHJ(flagp, 0);
683572
+                    }
683572
                     br = regbranch(pRExC_state, &flags, 1, depth+1);
683572
 		    if (br == 0) {
683572
                         RETURN_FAIL_ON_RESTART(flags,flagp);
683572
                         FAIL2("panic: regbranch returned failure, flags=%#" UVxf,
683572
                               (UV) flags);
683572
                     } else
683572
-                        REGTAIL(pRExC_state, br, reganode(pRExC_state,
683572
-                                                          LONGJMP, 0));
683572
+                    if (! REGTAIL(pRExC_state, br, reganode(pRExC_state,
683572
+                                                             LONGJMP, 0)))
683572
+                    {
683572
+                        REQUIRE_BRANCHJ(flagp, 0);
683572
+                    }
683572
 		    c = UCHARAT(RExC_parse);
683572
                     nextchar(pRExC_state);
683572
 		    if (flags&HASWIDTH)
683572
@@ -11939,7 +11955,9 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp, U32 depth)
683572
                             FAIL2("panic: regbranch returned failure, flags=%#" UVxf,
683572
                                   (UV) flags);
683572
                         }
683572
-                        REGTAIL(pRExC_state, ret, lastbr);
683572
+                        if (! REGTAIL(pRExC_state, ret, lastbr)) {
683572
+                            REQUIRE_BRANCHJ(flagp, 0);
683572
+                        }
683572
 		 	if (flags&HASWIDTH)
683572
 			    *flagp |= HASWIDTH;
683572
                         c = UCHARAT(RExC_parse);
683572
@@ -11954,16 +11972,26 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp, U32 depth)
683572
                             vFAIL("Switch (?(condition)... contains too many branches");
683572
                     }
683572
 		    ender = reg_node(pRExC_state, TAIL);
683572
-                    REGTAIL(pRExC_state, br, ender);
683572
+                    if (! REGTAIL(pRExC_state, br, ender)) {
683572
+                        REQUIRE_BRANCHJ(flagp, 0);
683572
+                    }
683572
 		    if (lastbr) {
683572
-                        REGTAIL(pRExC_state, lastbr, ender);
683572
-                        REGTAIL(pRExC_state, REGNODE_OFFSET(
683572
-                                                NEXTOPER(
683572
-                                                NEXTOPER(REGNODE_p(lastbr)))),
683572
-                                             ender);
683572
+                        if (! REGTAIL(pRExC_state, lastbr, ender)) {
683572
+                            REQUIRE_BRANCHJ(flagp, 0);
683572
+                        }
683572
+                        if (! REGTAIL(pRExC_state,
683572
+                                      REGNODE_OFFSET(
683572
+                                                 NEXTOPER(
683572
+                                                 NEXTOPER(REGNODE_p(lastbr)))),
683572
+                                      ender))
683572
+                        {
683572
+                            REQUIRE_BRANCHJ(flagp, 0);
683572
+                        }
683572
 		    }
683572
 		    else
683572
-                        REGTAIL(pRExC_state, ret, ender);
683572
+                        if (! REGTAIL(pRExC_state, ret, ender)) {
683572
+                            REQUIRE_BRANCHJ(flagp, 0);
683572
+                        }
683572
 #if 0  /* Removing this doesn't cause failures in the test suite -- khw */
683572
                     RExC_size++; /* XXX WHY do we need this?!!
683572
                                     For large programs it seems to be required
683572
@@ -12113,7 +12141,9 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp, U32 depth)
683572
 	*flagp |= flags&SIMPLE;
683572
     }
683572
     if (is_open) {				/* Starts with OPEN. */
683572
-        REGTAIL(pRExC_state, ret, br);          /* OPEN -> first. */
683572
+        if (! REGTAIL(pRExC_state, ret, br)) {  /* OPEN -> first. */
683572
+            REQUIRE_BRANCHJ(flagp, 0);
683572
+        }
683572
     }
683572
     else if (paren != '?')		/* Not Conditional */
683572
 	ret = br;
683572
@@ -12121,12 +12151,15 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp, U32 depth)
683572
     lastbr = br;
683572
     while (*RExC_parse == '|') {
683572
 	if (RExC_use_BRANCHJ) {
683572
+            bool shut_gcc_up;
683572
+
683572
 	    ender = reganode(pRExC_state, LONGJMP, 0);
683572
 
683572
             /* Append to the previous. */
683572
-            REGTAIL(pRExC_state,
683572
-                    REGNODE_OFFSET(NEXTOPER(NEXTOPER(REGNODE_p(lastbr)))),
683572
-                    ender);
683572
+            shut_gcc_up = REGTAIL(pRExC_state,
683572
+                         REGNODE_OFFSET(NEXTOPER(NEXTOPER(REGNODE_p(lastbr)))),
683572
+                         ender);
683572
+            PERL_UNUSED_VAR(shut_gcc_up);
683572
 	}
683572
 	nextchar(pRExC_state);
683572
 	if (freeze_paren) {
683572
@@ -12237,9 +12270,10 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp, U32 depth)
683572
                         is_nothing= 0;
683572
 		}
683572
 		else if (op == BRANCHJ) {
683572
-                    REGTAIL_STUDY(pRExC_state,
683572
-                                  REGNODE_OFFSET(NEXTOPER(NEXTOPER(br))),
683572
-                                  ender);
683572
+                    bool shut_gcc_up = REGTAIL_STUDY(pRExC_state,
683572
+                                        REGNODE_OFFSET(NEXTOPER(NEXTOPER(br))),
683572
+                                        ender);
683572
+                    PERL_UNUSED_VAR(shut_gcc_up);
683572
                     /* for now we always disable this optimisation * /
683572
                     if ( OP(NEXTOPER(NEXTOPER(br))) != NOTHING
683572
                          || regnext(NEXTOPER(NEXTOPER(br))) != REGNODE_p(ender))
683572
@@ -12551,7 +12585,9 @@ S_regpiece(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
683572
 		const regnode_offset w = reg_node(pRExC_state, WHILEM);
683572
 
683572
 		FLAGS(REGNODE_p(w)) = 0;
683572
-                REGTAIL(pRExC_state, ret, w);
683572
+                if (!  REGTAIL(pRExC_state, ret, w)) {
683572
+                    REQUIRE_BRANCHJ(flagp, 0);
683572
+                }
683572
 		if (RExC_use_BRANCHJ) {
683572
 		    reginsert(pRExC_state, LONGJMP, ret, depth+1);
683572
 		    reginsert(pRExC_state, NOTHING, ret, depth+1);
683572
@@ -12566,7 +12602,11 @@ S_regpiece(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
683572
 		if (RExC_use_BRANCHJ)
683572
                     NEXT_OFF(REGNODE_p(ret)) = 3;   /* Go over NOTHING to
683572
                                                        LONGJMP. */
683572
-                REGTAIL(pRExC_state, ret, reg_node(pRExC_state, NOTHING));
683572
+                if (! REGTAIL(pRExC_state, ret, reg_node(pRExC_state,
683572
+                                                          NOTHING)))
683572
+                {
683572
+                    REQUIRE_BRANCHJ(flagp, 0);
683572
+                }
683572
                 RExC_whilem_seen++;
683572
                 MARK_NAUGHTY_EXP(1, 4);     /* compound interest */
683572
 	    }
683572
@@ -12638,16 +12678,22 @@ S_regpiece(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
683572
     if (*RExC_parse == '?') {
683572
 	nextchar(pRExC_state);
683572
 	reginsert(pRExC_state, MINMOD, ret, depth+1);
683572
-        REGTAIL(pRExC_state, ret, ret + NODE_STEP_REGNODE);
683572
+        if (! REGTAIL(pRExC_state, ret, ret + NODE_STEP_REGNODE)) {
683572
+            REQUIRE_BRANCHJ(flagp, 0);
683572
+        }
683572
     }
683572
     else if (*RExC_parse == '+') {
683572
         regnode_offset ender;
683572
         nextchar(pRExC_state);
683572
         ender = reg_node(pRExC_state, SUCCEED);
683572
-        REGTAIL(pRExC_state, ret, ender);
683572
+        if (! REGTAIL(pRExC_state, ret, ender)) {
683572
+            REQUIRE_BRANCHJ(flagp, 0);
683572
+        }
683572
         reginsert(pRExC_state, SUSPEND, ret, depth+1);
683572
         ender = reg_node(pRExC_state, TAIL);
683572
-        REGTAIL(pRExC_state, ret, ender);
683572
+        if (! REGTAIL(pRExC_state, ret, ender)) {
683572
+            REQUIRE_BRANCHJ(flagp, 0);
683572
+        }
683572
     }
683572
 
683572
     if (ISMULT2(RExC_parse)) {
683572
@@ -19815,8 +19861,8 @@ S_regtail(pTHX_ RExC_state_t * pRExC_state,
683572
     }
683572
     else {
683572
         if (val - scan > U16_MAX) {
683572
-            /* Since not all callers check the return value, populate this with
683572
-             * something that won't loop and will likely lead to a crash if
683572
+            /* Populate this with something that won't loop and will likely
683572
+             * lead to a crash if the caller ignores the failure return, and
683572
              * execution continues */
683572
             NEXT_OFF(REGNODE_p(scan)) = U16_MAX;
683572
             return FALSE;
683572
@@ -19927,6 +19973,9 @@ S_regtail_study(pTHX_ RExC_state_t *pRExC_state, regnode_offset p,
683572
     }
683572
     else {
683572
         if (val - scan > U16_MAX) {
683572
+            /* Populate this with something that won't loop and will likely
683572
+             * lead to a crash if the caller ignores the failure return, and
683572
+             * execution continues */
683572
             NEXT_OFF(REGNODE_p(scan)) = U16_MAX;
683572
             return FALSE;
683572
         }
683572
diff --git a/t/re/bigfuzzy_not_utf8.t b/t/re/bigfuzzy_not_utf8.t
683572
new file mode 100644
683572
index 0000000000000000000000000000000000000000..b4dfd150a9297172af5d8e7811357fd68931f8d7
683572
GIT binary patch
683572
literal 36399
683572
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
683572
683572
literal 0
683572
HcmV?d00001
683572
683572
-- 
683572
2.21.0
683572