From: David Mitchell Date: Tue, 17 May 2016 08:23:00 +0000 (+0100) Subject: fix uplevel() under 5.23.8+ X-Git-Tag: rt112246^2~12 X-Git-Url: http://git.vpit.fr/?a=commitdiff_plain;h=f4167ba5f8779b2ae9174431fed29d3e0cd6411e;hp=f4167ba5f8779b2ae9174431fed29d3e0cd6411e;p=perl%2Fmodules%2FScope-Upper.git fix uplevel() under 5.23.8+ The old method of creating a new curstackinfo containing the faked-up new context stack no longer works. This is because leave_scope() is now called just prior to each context stack entry popping, and so a destructor which restores the old context array leaves a dangling pointer. E.g. pp_leavesub() on 5.23.8 onwards looks something like: cx = CX_CUR(); .... CX_LEAVE_SCOPE(cx); /* at this point the destructor has been called and the old context * stack back been restored; cx now points at freed garbage */ cx_popsub(cx); /* SEGV */ Conversely, now that it's guaranteed that the save stack is always processed prior to each context pop - regardless of whether its a normal scope exit or an exception - it allows us to use a simpler method to fake things up for uplevel(): just temporarily change the types of all the higher contexts to CXt_NULL so that they won't be seen by caller() etc. On scope exit the savestack destructor restores the old types, which are then processed and popped as normal. As well as setting each entry to CXt_NULL we set a flag, CXp_SU_UPLEVEL_NULLED (whose bit is currently unused by the perl core) to indicate that this is a temporarily ignored context. We then introduce a distinction between logical and physical context stack indices: functions like UP return a logical index which ignore all the nulled-out contexts; when such a logical value is passed as an arg to a function such as localize(), it is first converted back to a real index. The other main change is how uplevel() doctors the sub's arg list as seen by caller(): previously this was done by modifying the argarray field of the context entry for the just-called sub. Since 5.23.8 onwards doesn't have an argarray field, we instead modify the pad[0] of the running sub (which is what caller() examines now). Since there's no longer a possibility of getting argarray and pad[0] out of sync, the special fixups formerly required in the presence of goto are no longer required. Rather than rolling our own OP_ENTERSUB op, we just use call_sv() instead, with a PL_runops pointing to a temporary hook that allows the args to be fixed up on return from pp_entersub. After that, a normal runops loop is called. Since uplevel is so different under 5.23.8, I've split the original functions into su_uplevel_old/su_uplevel_new su_uplevel_restore_old/su_uplevel_restore_new with #defines compiling only one set. ---