summaryrefslogtreecommitdiff
path: root/regcomp.c
diff options
context:
space:
mode:
authorKarl Williamson <khw@cpan.org>2020-10-23 07:54:53 -0600
committerKarl Williamson <khw@cpan.org>2020-10-23 08:06:38 -0600
commitbb58640a409949759318542317e353e2241cc408 (patch)
treee764c72af9040a2662cb46927d90106c51d79e4d /regcomp.c
parent28df11c0263c8ebd0e2bc0436b4a01c84279fc42 (diff)
downloadperl-bb58640a409949759318542317e353e2241cc408.tar.gz
Fix GH #17278
This was an assertion failure in regexec.c under rare circumstances. A reduction of the fuzzed test case is now in pat_advanced.t The root cause of this was that the pattern being compiled was encoded in UTF-8 and 'use locale' was in effect, equivalent to the /l charset, and then the charset was reset inside the pattern, to /d. But /d in a UTF-8 patterns is illegal, hence the later assertion failure. The solution is to reset instead to /u when the pattern is UTF-8.
Diffstat (limited to 'regcomp.c')
-rw-r--r--regcomp.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/regcomp.c b/regcomp.c
index 3c08d7f979..bc4a9a130d 100644
--- a/regcomp.c
+++ b/regcomp.c
@@ -414,6 +414,11 @@ struct RExC_state_t {
} \
} STMT_END
+/* /u is to be chosen if we are supposed to use Unicode rules, or if the
+ * pattern is in UTF-8. This latter condition is in case the outermost rules
+ * are locale. See GH #17278 */
+#define toUSE_UNI_CHARSET_NOT_DEPENDS (RExC_uni_semantics || UTF)
+
/* Change from /d into /u rules, and restart the parse. RExC_uni_semantics is
* a flag that indicates we need to override /d with /u as a result of
* something in the pattern. It should only be used in regards to calling
@@ -7736,7 +7741,7 @@ Perl_re_op_compile(pTHX_ SV ** const patternp, int pat_count,
rx_flags = orig_rx_flags;
- if ( (UTF || RExC_uni_semantics)
+ if ( toUSE_UNI_CHARSET_NOT_DEPENDS
&& initial_charset == REGEX_DEPENDS_CHARSET)
{
@@ -10819,7 +10824,7 @@ S_parse_lparen_question_flags(pTHX_ RExC_state_t *pRExC_state)
RExC_parse++;
has_use_defaults = TRUE;
STD_PMMOD_FLAGS_CLEAR(&RExC_flags);
- cs = (RExC_uni_semantics)
+ cs = (toUSE_UNI_CHARSET_NOT_DEPENDS)
? REGEX_UNICODE_CHARSET
: REGEX_DEPENDS_CHARSET;
set_regex_charset(&RExC_flags, cs);
@@ -10827,7 +10832,7 @@ S_parse_lparen_question_flags(pTHX_ RExC_state_t *pRExC_state)
else {
cs = get_regex_charset(RExC_flags);
if ( cs == REGEX_DEPENDS_CHARSET
- && RExC_uni_semantics)
+ && (toUSE_UNI_CHARSET_NOT_DEPENDS))
{
cs = REGEX_UNICODE_CHARSET;
}
@@ -10911,7 +10916,7 @@ S_parse_lparen_question_flags(pTHX_ RExC_state_t *pRExC_state)
* pattern (or target, not known until runtime) are
* utf8, or something in the pattern indicates unicode
* semantics */
- cs = (RExC_uni_semantics)
+ cs = (toUSE_UNI_CHARSET_NOT_DEPENDS)
? REGEX_UNICODE_CHARSET
: REGEX_DEPENDS_CHARSET;
has_charset_modifier = DEPENDS_PAT_MOD;
@@ -12447,7 +12452,7 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp, U32 depth)
/* restore original flags, but keep (?p) and, if we've encountered
* something in the parse that changes /d rules into /u, keep the /u */
RExC_flags = oregflags | (RExC_flags & RXf_PMf_KEEPCOPY);
- if (DEPENDS_SEMANTICS && RExC_uni_semantics) {
+ if (DEPENDS_SEMANTICS && toUSE_UNI_CHARSET_NOT_DEPENDS) {
set_regex_charset(&RExC_flags, REGEX_UNICODE_CHARSET);
}
if (RExC_parse >= RExC_end || UCHARAT(RExC_parse) != ')') {