This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
PATCH: [perl #133921] Segfaults in regcomp.c
authorKarl Williamson <khw@cpan.org>
Thu, 14 Mar 2019 03:25:05 +0000 (21:25 -0600)
committerKarl Williamson <khw@cpan.org>
Thu, 14 Mar 2019 03:31:58 +0000 (21:31 -0600)
If a regular expression pattern gets too long so that the branch
instructions need more bits than are available, it is supposed to
reparse and use long jumps instead of the normal ones that don't take up
extra room.  The blamed commit caused the test for this to be done too
late.  This just moves the test to do it in time; lexically later in the
file, but just after the variable takes on the too-large value and
before it gets used in the next loop iteration.

regcomp.c
t/re/pat.t

index 51679e9..15d843e 100644 (file)
--- a/regcomp.c
+++ b/regcomp.c
@@ -12315,16 +12315,16 @@ S_regbranch(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, I32 first, U32 depth)
            /* FIXME adding one for every branch after the first is probably
             * excessive now we have TRIE support. (hv) */
            MARK_NAUGHTY(1);
-            if (     chain > (SSize_t) BRANCH_MAX_OFFSET
-                && ! RExC_use_BRANCHJ)
-            {
-                /* XXX We could just redo this branch, but figuring out what
-                 * bookkeeping needs to be reset is a pain */
-                REQUIRE_BRANCHJ(flagp, 0);
-            }
             REGTAIL(pRExC_state, chain, latest);
        }
        chain = latest;
+        if (     chain > (SSize_t) BRANCH_MAX_OFFSET
+            && ! RExC_use_BRANCHJ)
+        {
+            /* XXX We could just redo this branch, but figuring out what
+                * bookkeeping needs to be reset is a pain */
+            REQUIRE_BRANCHJ(flagp, 0);
+        }
        c++;
     }
     if (chain == 0) {  /* Loop ran zero times. */
index d4ac020..7bb215a 100644 (file)
@@ -24,7 +24,7 @@ BEGIN {
 skip_all('no re module') unless defined &DynaLoader::boot_DynaLoader;
 skip_all_without_unicode_tables();
 
-plan tests => 855;  # Update this when adding/deleting tests.
+plan tests => 857;  # Update this when adding/deleting tests.
 
 run_tests() unless caller;
 
@@ -2005,6 +2005,10 @@ CODE
     {   # [perl #133871], ASAN/valgrind out-of-bounds access
         fresh_perl_like('qr/(?|(())|())|//', qr/syntax error/, {}, "[perl #133871]");
     }
+    {   # [perl #133921], segfault
+        fresh_perl_is('qr\ 40||ß+p00000F00000ù\Q00000ÿ00000x00000x0c0e0\Qx0\Qx0\x{0c!}\;\;î0\x\0ÿÿÿþ\0\0\0ù\Q`\Qx`\0\ 1{0c!}\ 1e;\0\0\0ù\ò`\Qm`\x{0c!}\;\;îçÿ \0\7fç\0\0\0!\0F\ 5\0\0/;îçÿù\Q\0\ 1\0\0x\10ÿÿÿÿ\0\0\0ù\0\0\0\7f`x{0c!}\ 1e;\0\0\0ù\Q`\Qx`\x{c!}\;\;îç!}\;îçÿù\Q\87 \x\0ÿÿÿÿ\0\0>=\Qx`\Qx`\0\0ù\ò`\Qx`\x{0c!};\;îçÿ \0F\ 5\0n0t0\0\0\80\ 1d;t \0\0\0ù \0\7fç\80\0\0!00000000000000000000000m/00000000000000000000\ e00000000000m/\10\10\10\10\x{){} \10\10\10\10)|\10\10\ 4i', "", {}, "[perl #133921]");
+        fresh_perl_is('\ 4|ß+W0ü0r0\Qx0\Qx0x0c0G00000000000000000O000000000x0x0x0c!}\;îçÿù\Q0 \x\0ÿÿÿÿ\0\0\0ù\Q`\Qx`\0\ 1{0d ;\0\0\0ù\ò`\Qm`\x{0c!}\;\;îçÿ \0\7fç\0\0\0!\0F\ 5\0\0/;îçÿù\Q\0\ 1\0\0x\10ÿÿÿÿ\0\0\0ù\0\0\0\7f`x{0c!}\ 1;\0\0\0ù\Q`\Qq`\x{c!}\;\;îç!}\;îçÿù\Q\87 \x\0ÿÿÿÿ\0\0>=\Qx`\Qx`\0\0ù\ò`\Qx`\x{0c!};\;îçÿ \00000000F\ 5\0m0t0\0\0\80\ 1d;t \0\0\0ù \0\7fç\80\0\0!00000000000000000000000m/00000000000000000000\ e00000000000m/\10\10\10\10\x{){} \10\10\10\10)|\10\10\ 4\ 4i', "", {}, "[perl #133921]");
+    }
 
 } # End of sub run_tests