diff options
author | David Mitchell <davem@iabyn.com> | 2019-06-19 13:03:22 +0100 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2019-08-06 15:21:15 +0100 |
commit | 1d48e83dd8863e78e8422ed502d9b2f3199193f5 (patch) | |
tree | 9aa557ddb1d04d714383cf8d14243ad8f672036d /regexec.c | |
parent | 1d84a25665013f389ffc6fad7dd133f1c6287a08 (diff) | |
download | perl-1d48e83dd8863e78e8422ed502d9b2f3199193f5.tar.gz |
avoid use-after free in /(?{...})/
RT #134208
In something like
eval { sub { " " }->() =~ /(?{ die })/ }
When the match string gets aliased to $_, the SAVE_DEFSV is done after the
SAVEDESTRUCTOR_X(S_cleanup_regmatch_info_aux). So if croaking, the SV
gets SvREFCNT_dec()ed by the SAVE_DEFSV, then S_cleanup_regmatch_info_aux()
manipulates the SV's magic.
This doesn't cause a problem unless the match string is temporary, in
which case the only other reference keeping it alive will be removed
by the FREETMPs during the croak.
The fix is to make sure an extra ref to the sv is held.
Diffstat (limited to 'regexec.c')
-rw-r--r-- | regexec.c | 4 |
1 files changed, 4 insertions, 0 deletions
@@ -10233,6 +10233,7 @@ S_setup_eval_state(pTHX_ regmatch_info *const reginfo) regmatch_info_aux_eval *eval_state = reginfo->info_aux_eval; eval_state->rex = rex; + eval_state->sv = reginfo->sv; if (reginfo->sv) { /* Make $_ available to executed code. */ @@ -10240,6 +10241,8 @@ S_setup_eval_state(pTHX_ regmatch_info *const reginfo) SAVE_DEFSV; DEFSV_set(reginfo->sv); } + /* will be dec'd by S_cleanup_regmatch_info_aux */ + SvREFCNT_inc_NN(reginfo->sv); if (!(mg = mg_find_mglob(reginfo->sv))) { /* prepare for quick setting of pos */ @@ -10331,6 +10334,7 @@ S_cleanup_regmatch_info_aux(pTHX_ void *arg) } PL_curpm = eval_state->curpm; + SvREFCNT_dec(eval_state->sv); } PL_regmatch_state = aux->old_regmatch_state; |