Skip to content
Permalink
Browse files Browse the repository at this point in the history
study_chunk: extract rck_elide_nothing
(CVE-2020-10878)

(cherry picked from commit 93dee06613d4e1428fb10905ce1c3c96f53113dc)
  • Loading branch information
hvds authored and steve-m-hay committed May 17, 2020
1 parent 897d1f7 commit 0a320d7
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 27 deletions.
1 change: 1 addition & 0 deletions embed.fnc
Expand Up @@ -2481,6 +2481,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
Expand Down
1 change: 1 addition & 0 deletions embed.h
Expand Up @@ -1208,6 +1208,7 @@
#define parse_lparen_question_flags(a) S_parse_lparen_question_flags(aTHX_ a)
#define parse_uniprop_string(a,b,c,d,e,f,g,h,i) Perl_parse_uniprop_string(aTHX_ a,b,c,d,e,f,g,h,i)
#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)
Expand Down
3 changes: 3 additions & 0 deletions proto.h
Expand Up @@ -5543,6 +5543,9 @@ PERL_CALLCONV SV * Perl_parse_uniprop_string(pTHX_ const char * const name, cons
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 \
Expand Down
70 changes: 43 additions & 27 deletions regcomp.c
Expand Up @@ -4450,6 +4450,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,
Expand Down Expand Up @@ -4550,28 +4588,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. */
Expand Down Expand Up @@ -5745,11 +5765,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:
Expand Down

0 comments on commit 0a320d7

Please sign in to comment.