diff options
author | Hugo van der Sanden <hv@crypt.org> | 2020-02-18 13:51:16 +0000 |
---|---|---|
committer | Steve Hay <steve.m.hay@googlemail.com> | 2020-05-17 10:34:27 +0100 |
commit | 011cd8913d3a230b8d30b156b848585c7c4c1597 (patch) | |
tree | 1bc922e31d54e64185f7c72f289f123d5410fa66 | |
parent | 1aef74e6bc0269fcd6ad7669fcd58488ffaf736f (diff) | |
download | perl-011cd8913d3a230b8d30b156b848585c7c4c1597.tar.gz |
study_chunk: extract rck_elide_nothing
(CVE-2020-10878)
(cherry picked from commit a3a7598c8ec6efb0eb9c0b786d80c4d2a3751b70)
-rw-r--r-- | embed.fnc | 1 | ||||
-rw-r--r-- | embed.h | 1 | ||||
-rw-r--r-- | proto.h | 3 | ||||
-rw-r--r-- | regcomp.c | 70 |
4 files changed, 48 insertions, 27 deletions
@@ -2477,6 +2477,7 @@ Es |SSize_t|study_chunk |NN RExC_state_t *pRExC_state \ |I32 stopparen|U32 recursed_depth \ |NULLOK regnode_ssc *and_withp \ |U32 flags|U32 depth +Es |void |rck_elide_nothing|NN regnode *node EsR |SV * |get_ANYOFM_contents|NN const regnode * n EsRn |U32 |add_data |NN RExC_state_t* const pRExC_state \ |NN const char* const s|const U32 n @@ -1202,6 +1202,7 @@ #define output_or_return_posix_warnings(a,b,c) S_output_or_return_posix_warnings(aTHX_ a,b,c) #define parse_lparen_question_flags(a) S_parse_lparen_question_flags(aTHX_ a) #define populate_ANYOF_from_invlist(a,b) S_populate_ANYOF_from_invlist(aTHX_ a,b) +#define rck_elide_nothing(a) S_rck_elide_nothing(aTHX_ a) #define reg(a,b,c,d) S_reg(aTHX_ a,b,c,d) #define reg2Lanode(a,b,c,d) S_reg2Lanode(aTHX_ a,b,c,d) #define reg_node(a,b) S_reg_node(aTHX_ a,b) @@ -5485,6 +5485,9 @@ STATIC void S_parse_lparen_question_flags(pTHX_ RExC_state_t *pRExC_state); STATIC void S_populate_ANYOF_from_invlist(pTHX_ regnode *node, SV** invlist_ptr); #define PERL_ARGS_ASSERT_POPULATE_ANYOF_FROM_INVLIST \ assert(node); assert(invlist_ptr) +STATIC void S_rck_elide_nothing(pTHX_ regnode *node); +#define PERL_ARGS_ASSERT_RCK_ELIDE_NOTHING \ + assert(node) PERL_STATIC_NO_RET void S_re_croak2(pTHX_ bool utf8, const char* pat1, const char* pat2, ...) __attribute__noreturn__; #define PERL_ARGS_ASSERT_RE_CROAK2 \ @@ -4178,6 +4178,44 @@ S_unwind_scan_frames(pTHX_ const void *p) } while (f); } +/* Follow the next-chain of the current node and optimize away + all the NOTHINGs from it. + */ +STATIC void +S_rck_elide_nothing(pTHX_ regnode *node) +{ + dVAR; + + PERL_ARGS_ASSERT_RCK_ELIDE_NOTHING; + + if (OP(node) != CURLYX) { + const int max = (reg_off_by_arg[OP(node)] + ? I32_MAX + /* I32 may be smaller than U16 on CRAYs! */ + : (I32_MAX < U16_MAX ? I32_MAX : U16_MAX)); + int off = (reg_off_by_arg[OP(node)] ? ARG(node) : NEXT_OFF(node)); + int noff; + regnode *n = node; + + /* Skip NOTHING and LONGJMP. */ + while ( + (n = regnext(n)) + && ( + (PL_regkind[OP(n)] == NOTHING && (noff = NEXT_OFF(n))) + || ((OP(n) == LONGJMP) && (noff = ARG(n))) + ) + && off + noff < max + ) { + off += noff; + } + if (reg_off_by_arg[OP(node)]) + ARG(node) = off; + else + NEXT_OFF(node) = off; + } + return; +} + /* the return from this sub is the minimum length that could possibly match */ STATIC SSize_t S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp, @@ -4277,28 +4315,10 @@ S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp, */ JOIN_EXACT(scan,&min_subtract, &unfolded_multi_char, 0); - /* Follow the next-chain of the current node and optimize - away all the NOTHINGs from it. */ - if (OP(scan) != CURLYX) { - const int max = (reg_off_by_arg[OP(scan)] - ? I32_MAX - /* I32 may be smaller than U16 on CRAYs! */ - : (I32_MAX < U16_MAX ? I32_MAX : U16_MAX)); - int off = (reg_off_by_arg[OP(scan)] ? ARG(scan) : NEXT_OFF(scan)); - int noff; - regnode *n = scan; - - /* Skip NOTHING and LONGJMP. */ - while ((n = regnext(n)) - && ((PL_regkind[OP(n)] == NOTHING && (noff = NEXT_OFF(n))) - || ((OP(n) == LONGJMP) && (noff = ARG(n)))) - && off + noff < max) - off += noff; - if (reg_off_by_arg[OP(scan)]) - ARG(scan) = off; - else - NEXT_OFF(scan) = off; - } + /* Follow the next-chain of the current node and optimize + away all the NOTHINGs from it. + */ + rck_elide_nothing(scan); /* The principal pseudo-switch. Cannot be a switch, since we look into several different things. */ @@ -5425,11 +5445,7 @@ Perl_re_printf( aTHX_ "LHS=%" UVuf " RHS=%" UVuf "\n", if (data && (fl & SF_HAS_EVAL)) data->flags |= SF_HAS_EVAL; optimize_curly_tail: - if (OP(oscan) != CURLYX) { - while (PL_regkind[OP(next = regnext(oscan))] == NOTHING - && NEXT_OFF(next)) - NEXT_OFF(oscan) += NEXT_OFF(next); - } + rck_elide_nothing(oscan); continue; default: |