106 lines
4.3 KiB
Diff
106 lines
4.3 KiB
Diff
|
From dc1f8f6b581a8e4efbb782398ab3e7c3a52b062f Mon Sep 17 00:00:00 2001
|
||
|
From: Karl Williamson <khw@cpan.org>
|
||
|
Date: Tue, 8 May 2018 12:13:18 -0600
|
||
|
Subject: [PATCH] PATCH: [perl #133185] Infinite loop in qr//
|
||
|
MIME-Version: 1.0
|
||
|
Content-Type: text/plain; charset=UTF-8
|
||
|
Content-Transfer-Encoding: 8bit
|
||
|
|
||
|
This loop was inadvertently introduced as part of patches to fix
|
||
|
(perl #132227 CVE-2018-6797] heap-buffer-overflow". The commit in 5.27
|
||
|
responsible was f8fb8615ddc5a80e3bbd4386a8914497f921b62d.
|
||
|
|
||
|
To be vulnerable, the pattern must start out as /d (hence no use 5.012
|
||
|
or higher), and then there must be something that implicitly forces /u
|
||
|
(which the \pp does in the test case added by this patch), and then
|
||
|
(?aa), and then the code point \xDF. (German Sharp S). The /i must be
|
||
|
in effect by the time the DF is encountered, but it needn't come in the
|
||
|
(?aa) which the test does.
|
||
|
|
||
|
The problem is that the conditional that is testing that we switched
|
||
|
away from /d rules is assuming that this happened during the
|
||
|
construction of the current EXACTFish node. The comments I wrote
|
||
|
indicate this assumption. But this example shows that the switch can
|
||
|
come before this node started getting constructed, and so it loops.
|
||
|
|
||
|
The patch explicitly saves the state at the beginning of this node's
|
||
|
construction, and only retries if it changed during that construction.
|
||
|
Therefore the next time through, it will see that it hasn't changed
|
||
|
since the previous time, and won't loop.
|
||
|
|
||
|
Petr Písař: Ported to 5.26.2 from:
|
||
|
|
||
|
commit 0b9cb33b146b3eb55634853f883a880771dd1413
|
||
|
Author: Karl Williamson <khw@cpan.org>
|
||
|
Date: Tue May 8 12:13:18 2018 -0600
|
||
|
|
||
|
PATCH: [perl #133185] Infinite loop in qr//
|
||
|
|
||
|
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
||
|
---
|
||
|
regcomp.c | 10 +++++++++-
|
||
|
t/re/speed.t | 5 ++++-
|
||
|
2 files changed, 13 insertions(+), 2 deletions(-)
|
||
|
|
||
|
diff --git a/regcomp.c b/regcomp.c
|
||
|
index 845e660..18fa465 100644
|
||
|
--- a/regcomp.c
|
||
|
+++ b/regcomp.c
|
||
|
@@ -13100,6 +13100,10 @@ S_regatom(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
|
||
|
bool maybe_exactfu = PASS2
|
||
|
&& (node_type == EXACTF || node_type == EXACTFL);
|
||
|
|
||
|
+ /* To see if RExC_uni_semantics changes during parsing of the node.
|
||
|
+ * */
|
||
|
+ bool uni_semantics_at_node_start;
|
||
|
+
|
||
|
/* If a folding node contains only code points that don't
|
||
|
* participate in folds, it can be changed into an EXACT node,
|
||
|
* which allows the optimizer more things to look for */
|
||
|
@@ -13147,6 +13151,8 @@ S_regatom(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
|
||
|
|| UTF8_IS_INVARIANT(UCHARAT(RExC_parse))
|
||
|
|| UTF8_IS_START(UCHARAT(RExC_parse)));
|
||
|
|
||
|
+ uni_semantics_at_node_start = RExC_uni_semantics;
|
||
|
+
|
||
|
/* Here, we have a literal character. Find the maximal string of
|
||
|
* them in the input that we can fit into a single EXACTish node.
|
||
|
* We quit at the first non-literal or when the node gets full */
|
||
|
@@ -13550,7 +13556,9 @@ S_regatom(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
|
||
|
* didn't think it needed to reparse. But this
|
||
|
* sharp s now does indicate the need for
|
||
|
* reparsing. */
|
||
|
- if (RExC_uni_semantics) {
|
||
|
+ if ( uni_semantics_at_node_start
|
||
|
+ != RExC_uni_semantics)
|
||
|
+ {
|
||
|
p = oldp;
|
||
|
goto loopdone;
|
||
|
}
|
||
|
diff --git a/t/re/speed.t b/t/re/speed.t
|
||
|
index 4a4830f..9a57de1 100644
|
||
|
--- a/t/re/speed.t
|
||
|
+++ b/t/re/speed.t
|
||
|
@@ -24,7 +24,7 @@ BEGIN {
|
||
|
skip_all('no re module') unless defined &DynaLoader::boot_DynaLoader;
|
||
|
skip_all_without_unicode_tables();
|
||
|
|
||
|
-plan tests => 58; #** update watchdog timeouts proportionally when adding tests
|
||
|
+plan tests => 59; #** update watchdog timeouts proportionally when adding tests
|
||
|
|
||
|
use strict;
|
||
|
use warnings;
|
||
|
@@ -156,6 +156,9 @@ PROG
|
||
|
ok( $elapsed <= 1, "should not COW on long string with substr and m//g");
|
||
|
}
|
||
|
|
||
|
+ # [perl #133185] Infinite loop
|
||
|
+ like("!\xdf", eval 'qr/\pp(?aai)\xdf/',
|
||
|
+ 'Compiling qr/\pp(?aai)\xdf/ doesn\'t loop');
|
||
|
|
||
|
} # End of sub run_tests
|
||
|
|
||
|
--
|
||
|
2.14.3
|
||
|
|