From 23388f01ab6c8081240ed70e7eea4936114e0e44 Mon Sep 17 00:00:00 2001 From: Petr Písař Date: Nov 30 2018 14:11:05 +0000 Subject: Fix compiling regular expressions that contain both compile- and run-time compiled code blocks --- diff --git a/perl-5.29.5-handle-code-mixed-compile-and-runtime.patch b/perl-5.29.5-handle-code-mixed-compile-and-runtime.patch new file mode 100644 index 0000000..f296d7c --- /dev/null +++ b/perl-5.29.5-handle-code-mixed-compile-and-runtime.patch @@ -0,0 +1,118 @@ +From 278d8c58e85c646b61e60fe48207e090278bb61c Mon Sep 17 00:00:00 2001 +From: David Mitchell +Date: Tue, 27 Nov 2018 13:26:39 +0000 +Subject: [PATCH] handle /(?(?{code}))/ mixed compile-and runtime +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Where a runtime pattern contains both compile-time and run-time code +blocks, e.g.: + + $re = '(?{ RRR })'; + / $re X(?{ CCC })Y/ + +The compile-time code-block CCC is parsed at the same time as the +surrounding text. The runtime code RRR is parsed at runtime by +constructing a fake pattern and re-parsing it, but with any compile-time +code-blocks blanked out (so they don't get compiled twice). The compiled +regex is then thrown away, but any optrees just created for the runtime +code blocks are kept. + +For example at runtime, the re-parsed pattern looks like: + + / (?{ RRR }) X__________Y/ + +Unfortunately this was failing for the conditional pattern, e.g. + + / $re X(?(?{ CCC }))Y/ + +which was getting blanked as + + / (?{ RRR }) X(?_______)Y/ + +which isn't valid syntax. + +This commit blanks (?{...}) into (?=====) instead which is always legal. + +Signed-off-by: Petr Písař +--- + regcomp.c | 24 +++++++++++++++++++----- + t/re/pat_re_eval.t | 17 ++++++++++++++++- + 2 files changed, 35 insertions(+), 6 deletions(-) + +diff --git a/regcomp.c b/regcomp.c +index bf987f6e28..ff26f2242f 100644 +--- a/regcomp.c ++++ b/regcomp.c +@@ -6756,13 +6756,27 @@ S_compile_runtime_code(pTHX_ RExC_state_t * const pRExC_state, + && n < pRExC_state->code_blocks->count + && s == pRExC_state->code_blocks->cb[n].start) + { +- /* blank out literal code block */ +- assert(pat[s] == '('); +- while (s <= pRExC_state->code_blocks->cb[n].end) { +- *p++ = '_'; ++ /* blank out literal code block so that they aren't ++ * recompiled: eg change from/to: ++ * /(?{xyz})/ ++ * /(?=====)/ ++ * and ++ * /(??{xyz})/ ++ * /(?======)/ ++ * and ++ * /(?(?{xyz}))/ ++ * /(?(?=====))/ ++ */ ++ assert(pat[s] == '('); ++ assert(pat[s+1] == '?'); ++ *p++ = '('; ++ *p++ = '?'; ++ s += 2; ++ while (s < pRExC_state->code_blocks->cb[n].end) { ++ *p++ = '='; + s++; + } +- s--; ++ *p++ = ')'; + n++; + continue; + } +diff --git a/t/re/pat_re_eval.t b/t/re/pat_re_eval.t +index f88a8651a1..8325451377 100644 +--- a/t/re/pat_re_eval.t ++++ b/t/re/pat_re_eval.t +@@ -23,7 +23,7 @@ BEGIN { + + our @global; + +-plan tests => 502; # Update this when adding/deleting tests. ++plan tests => 504; # Update this when adding/deleting tests. + + run_tests() unless caller; + +@@ -1301,6 +1301,21 @@ sub run_tests { + ok /^$qr$/, "RT #132772 - run time time qr//"; + } + ++ # RT #133687 ++ # mixing compile-time (?(?{code})) with run-time code blocks ++ # was failing, because the second pass through the parser ++ # (which compiles the runtime code blocks) was failing to adequately ++ # mask the compile-time code blocks to shield them from a second ++ # compile: /X(?{...})Y/ was being correctly masked as /X________Y/ ++ # but /X(?(?{...}))Y/ was being incorrectly masked as ++ # /X(?________)Y/ ++ ++ { ++ use re 'eval'; ++ my $runtime_re = '(??{ "A"; })'; ++ ok "ABC" =~ /^ $runtime_re (?(?{ 1; })BC) $/x, 'RT #133687 yes'; ++ ok "ABC" =~ /^ $runtime_re (?(?{ 0; })xy|BC) $/x, 'RT #133687 yes|no'; ++ } + + } # End of sub run_tests + +-- +2.17.2 + diff --git a/perl.spec b/perl.spec index dfcb6bb..db38504 100644 --- a/perl.spec +++ b/perl.spec @@ -211,6 +211,10 @@ Patch35: perl-5.29.5-perl-133659-move-argvout-cleanup-to-a-new-function.p Patch36: perl-5.29.5-perl-133659-tests-for-global-destruction-handling-of.patch Patch37: perl-5.29.5-perl-133659-make-an-in-place-edit-successful-if-the-.patch +# Fix compiling regular expressions that contain both compile- and run-time +# compiled code blocks, RT#133687, in upstream after 5.29.5 +Patch38: perl-5.29.5-handle-code-mixed-compile-and-runtime.patch + # Link XS modules to libperl.so with EU::CBuilder on Linux, bug #960048 Patch200: perl-5.16.3-Link-XS-modules-to-libperl.so-with-EU-CBuilder-on-Li.patch @@ -2799,6 +2803,7 @@ Perl extension for Version Objects %patch35 -p1 %patch36 -p1 %patch37 -p1 +%patch38 -p1 %patch200 -p1 %patch201 -p1 @@ -2835,6 +2840,7 @@ perl -x patchlevel.h \ 'Fedora Patch33: Fix PathTools tests to cope with ESTALE error (RT#133534)' \ 'Fedora Patch34: Fix an undefined behaviour in S_hv_delete_common()' \ 'Fedora Patch35: Fix in-place edit to replace files on a successful perl exit status (bug #1650041)' \ + 'Fedora Patch38: Fix compiling regular expressions that contain both compile- and run-time compiled code blocks (RT#133687)' \ 'Fedora Patch200: Link XS modules to libperl.so with EU::CBuilder on Linux' \ 'Fedora Patch201: Link XS modules to libperl.so with EU::MM on Linux' \ %{nil} @@ -5130,6 +5136,8 @@ popd - Fix an undefined behaviour in S_hv_delete_common() - Fix in-place edit to replace files on a successful perl exit status (bug #1650041) +- Fix compiling regular expressions that contain both compile- and run-time + compiled code blocks (RT#133687) * Fri Nov 30 2018 Petr Pisar - 4:5.28.1-426 - Install Encode developmental files when installing complete Perl