Fix compiling regular expressions that contain both compile- and run-time compiled code blocks

This commit is contained in:
Petr Písař 2018-11-30 14:28:58 +01:00
parent 45b1f54fc1
commit bfd9d6a2ae
2 changed files with 126 additions and 0 deletions

View File

@ -0,0 +1,118 @@
From 278d8c58e85c646b61e60fe48207e090278bb61c Mon Sep 17 00:00:00 2001
From: David Mitchell <davem@iabyn.com>
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ř <ppisar@redhat.com>
---
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

View File

@ -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 Jitka Plesnikova <jplesnik@redhat.com> - 4:5.28.1-426
- 5.28.1 bump