From: Vincent Pit Date: Thu, 1 Oct 2015 13:09:17 +0000 (-0300) Subject: Execute magic callbacks into separate stacks X-Git-Tag: rt107294^0 X-Git-Url: http://git.vpit.fr/?p=perl%2Fmodules%2FVariable-Magic.git;a=commitdiff_plain;h=d9d2fa9ce2900e97a1f4756bf51a0b6c9bd56c18 Execute magic callbacks into separate stacks When magic triggered, stack corruption could occur since the magic callback arguments were passed on the same stack as the ambient one. This issue has long gone unnoticed because most ops first unpack their stack arguments before processing magic, but also because this module is mostly used in practice to capture magic outside of the usual program op structure were the argument stack is relevant. This was made visible with core change 6442877a (publicized in perl 5.22.0) which caused get magic on transliterations to happen on the same C argument list as a PUSHmortal. This resulted in an undefined behaviour which was usually resolved by the magic being processed first (for example by gcc), but cl.exe on win32 prefers to execute the PUSHmortal first, hence the stack was corrupted. This fixes RT #107294. --- diff --git a/Magic.xs b/Magic.xs index 69ad981..432eeed 100644 --- a/Magic.xs +++ b/Magic.xs @@ -857,6 +857,8 @@ static SV *vmg_data_new(pTHX_ SV *ctor, SV *sv, SV **args, I32 items) { ENTER; SAVETMPS; + PUSHSTACKi(PERLSI_MAGIC); + PUSHMARK(SP); EXTEND(SP, items + 1); PUSHs(sv_2mortal(newRV_inc(sv))); @@ -875,6 +877,8 @@ static SV *vmg_data_new(pTHX_ SV *ctor, SV *sv, SV **args, I32 items) { #endif PUTBACK; + POPSTACK; + FREETMPS; LEAVE; @@ -1260,6 +1264,8 @@ static int vmg_cb_call(pTHX_ SV *cb, unsigned int flags, SV *sv, ...) { ENTER; SAVETMPS; + PUSHSTACKi(PERLSI_MAGIC); + PUSHMARK(SP); EXTEND(SP, args + 1); PUSHs(sv_2mortal(newRV_inc(sv))); @@ -1294,6 +1300,8 @@ static int vmg_cb_call(pTHX_ SV *cb, unsigned int flags, SV *sv, ...) { svr = NULL; PUTBACK; + POPSTACK; + FREETMPS; LEAVE; @@ -1370,6 +1378,8 @@ static U32 vmg_svt_len(pTHX_ SV *sv, MAGIC *mg) { ENTER; SAVETMPS; + PUSHSTACKi(PERLSI_MAGIC); + PUSHMARK(SP); EXTEND(SP, 3); PUSHs(sv_2mortal(newRV_inc(sv))); @@ -1397,6 +1407,8 @@ static U32 vmg_svt_len(pTHX_ SV *sv, MAGIC *mg) { --ret; PUTBACK; + POPSTACK; + FREETMPS; LEAVE; @@ -1571,6 +1583,8 @@ static int vmg_svt_free(pTHX_ SV *sv, MAGIC *mg) { ENTER; SAVETMPS; + PUSHSTACKi(PERLSI_MAGIC); + PUSHMARK(SP); EXTEND(SP, 2); PUSHs(sv_2mortal(newRV_inc(sv))); @@ -1598,6 +1612,8 @@ static int vmg_svt_free(pTHX_ SV *sv, MAGIC *mg) { ret = (int) SvIV(svr); PUTBACK; + POPSTACK; + FREETMPS; LEAVE;