diff options
author | Yves Orton <demerphq@gmail.com> | 2017-06-26 13:19:55 +0200 |
---|---|---|
committer | Steve Hay <steve.m.hay@googlemail.com> | 2018-11-05 20:15:46 +0000 |
commit | dabe076af345ab4512ea80245b4e4cd7ec0996cd (patch) | |
tree | e381014fced47a075e03c397fa75d1d3f7501ffc /regcomp.c | |
parent | c1c28ce6ba90ee05aa96b11ad551a6063680f3b9 (diff) | |
download | perl-dabe076af345ab4512ea80245b4e4cd7ec0996cd.tar.gz |
fix #131649 - extended charclass can trigger assert
The extended charclass parser makes some assumptions during the
first pass which are only true on well structured input, and it
does not properly catch various errors. later on the code assumes
that things the first pass will let through are valid, when in
fact they should trigger errors.
(cherry picked from commit 19a498a461d7c81ae3507c450953d1148efecf4f)
Diffstat (limited to 'regcomp.c')
-rw-r--r-- | regcomp.c | 28 |
1 files changed, 18 insertions, 10 deletions
@@ -14840,8 +14840,9 @@ S_handle_regex_sets(pTHX_ RExC_state_t *pRExC_state, SV** return_invlist, TRUE /* Force /x */ ); switch (*RExC_parse) { - case '?': - if (RExC_parse[1] == '[') depth++, RExC_parse++; + case '(': + if (RExC_parse[1] == '?' && RExC_parse[2] == '[') + depth++, RExC_parse+=2; /* FALLTHROUGH */ default: break; @@ -14898,9 +14899,9 @@ S_handle_regex_sets(pTHX_ RExC_state_t *pRExC_state, SV** return_invlist, } case ']': - if (depth--) break; - RExC_parse++; - if (*RExC_parse == ')') { + if (RExC_parse[1] == ')') { + RExC_parse++; + if (depth--) break; node = reganode(pRExC_state, ANYOF, 0); RExC_size += ANYOF_SKIP; nextchar(pRExC_state); @@ -14912,20 +14913,25 @@ S_handle_regex_sets(pTHX_ RExC_state_t *pRExC_state, SV** return_invlist, return node; } - goto no_close; + /* We output the messages even if warnings are off, because we'll fail + * the very next thing, and these give a likely diagnosis for that */ + if (posix_warnings && av_tindex_skip_len_mg(posix_warnings) >= 0) { + output_or_return_posix_warnings(pRExC_state, posix_warnings, NULL); + } + RExC_parse++; + vFAIL("Unexpected ']' with no following ')' in (?[..."); } RExC_parse += UTF ? UTF8SKIP(RExC_parse) : 1; } - no_close: /* We output the messages even if warnings are off, because we'll fail * the very next thing, and these give a likely diagnosis for that */ if (posix_warnings && av_tindex_skip_len_mg(posix_warnings) >= 0) { output_or_return_posix_warnings(pRExC_state, posix_warnings, NULL); } - FAIL("Syntax error in (?[...])"); + vFAIL("Syntax error in (?[...])"); } /* Pass 2 only after this. */ @@ -15105,12 +15111,14 @@ redo_curchar: * inversion list, and RExC_parse points to the trailing * ']'; the next character should be the ')' */ RExC_parse++; - assert(UCHARAT(RExC_parse) == ')'); + if (UCHARAT(RExC_parse) != ')') + vFAIL("Expecting close paren for nested extended charclass"); /* Then the ')' matching the original '(' handled by this * case: statement */ RExC_parse++; - assert(UCHARAT(RExC_parse) == ')'); + if (UCHARAT(RExC_parse) != ')') + vFAIL("Expecting close paren for wrapper for nested extended charclass"); RExC_flags = save_flags; goto handle_operand; |