-
-
Save tpunt/b1e81faf925ed474c29191ccf7bd7200 to your computer and use it in GitHub Desktop.
Stack Interruption
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
zend_execute_data *paused_stack; | |
PHP_FUNCTION(interrupt_stack) | |
{ | |
size_t stack_size = 0; | |
zend_execute_data *call_frame = execute_data->prev_execute_data; // get interrupt_stack() call site | |
++call_frame->opline; // skips the interrupt_stack() function call from the call site | |
for (; call_frame; call_frame = call_frame->prev_execute_data) { | |
stack_size += ZEND_CALL_FRAME_SLOT + ZEND_CALL_NUM_ARGS(call_frame); | |
} | |
paused_stack = (zend_execute_data *) emalloc(sizeof(zval) * stack_size); | |
call_frame = execute_data->prev_execute_data; | |
size_t saved_size = 0; | |
zend_execute_data *prev_frame = NULL; | |
while (call_frame) { | |
size_t frame_size = ZEND_CALL_FRAME_SLOT + ZEND_CALL_NUM_ARGS(call_frame); | |
zend_execute_data *tmp_frame; | |
saved_size += frame_size; | |
tmp_frame = (zend_execute_data *)((zval *)paused_stack + stack_size - saved_size); | |
memcpy(tmp_frame, call_frame, sizeof(zval) * frame_size); | |
tmp_frame->prev_execute_data = prev_frame; | |
// try fast-forwarding the oplines to the last opcode | |
// for (; call_frame->opline && call_frame->opline->opcode != ZEND_RETURN; ++call_frame->opline); | |
prev_frame = tmp_frame; | |
tmp_frame = call_frame->prev_execute_data; | |
zend_vm_stack_free_call_frame(call_frame); | |
call_frame = tmp_frame; | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
function test2() | |
{ | |
interrupt_stack(); | |
var_dump(2); // should not be output | |
} | |
function test() | |
{ | |
test2(); | |
var_dump(3); // should not be output | |
} | |
test(); | |
var_dump(1); // should not be output |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment