This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
regcomp.c: Don't forget to restore state
authorKarl Williamson <khw@cpan.org>
Fri, 27 Oct 2017 15:51:23 +0000 (09:51 -0600)
committerKarl Williamson <khw@cpan.org>
Fri, 27 Oct 2017 16:22:10 +0000 (10:22 -0600)
In code reading (so I don't have a test case), I realized that this code
could return out of its function without restoring the state that it has
changed out from under the caller, and that can lead to havoc when the
caller continues on assuming the original state.

This commit moves the return and other checking to after the state
restoral code.  It can call FAIL2 as part of a panic after the state the
failure is in is gone.  This would be a problem if it called vFAIL2
instead, but isn't because FAIL2 doesn't need the state the failure was
in.

regcomp.c

index 688da6a..c618cc1 100644 (file)
--- a/regcomp.c
+++ b/regcomp.c
@@ -12216,15 +12216,7 @@ S_grok_bslash_N(pTHX_ RExC_state_t *pRExC_state,
         RExC_recode_x_to_native = 1;
 #endif
 
-            if (!(*node_p = reg(pRExC_state, 1, &flags, depth+1))) {
-                if (flags & (RESTART_PASS1|NEED_UTF8)) {
-                    *flagp = flags & (RESTART_PASS1|NEED_UTF8);
-                    return FALSE;
-                }
-                FAIL2("panic: reg returned NULL to grok_bslash_N, flags=%#" UVxf,
-                    (UV) flags);
-            }
-            *flagp |= flags&(HASWIDTH|SPSTART|SIMPLE|POSTPONED);
+        *node_p = reg(pRExC_state, 1, &flags, depth+1);
 
         /* Restore the saved values */
        RExC_start = RExC_adjusted_start = save_start;
@@ -12233,8 +12225,18 @@ S_grok_bslash_N(pTHX_ RExC_state_t *pRExC_state,
 #ifdef EBCDIC
         RExC_recode_x_to_native = 0;
 #endif
-
         SvREFCNT_dec_NN(substitute_parse);
+
+        if (! *node_p) {
+            if (flags & (RESTART_PASS1|NEED_UTF8)) {
+                *flagp = flags & (RESTART_PASS1|NEED_UTF8);
+                return FALSE;
+            }
+            FAIL2("panic: reg returned NULL to grok_bslash_N, flags=%#" UVxf,
+                (UV) flags);
+        }
+        *flagp |= flags&(HASWIDTH|SPSTART|SIMPLE|POSTPONED);
+
         nextchar(pRExC_state);
 
         return TRUE;