static int32_t qb_transfer_variables_to_generator(qb_interpreter_context *cxt) { USE_TSRM zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); zval *ret, *ret_key; // reusing previous key and value if(generator->value) { ret = generator->value; } else { ALLOC_INIT_ZVAL(ret); generator->value = ret; } if(generator->key) { ret_key = generator->key; } else { ALLOC_INIT_ZVAL(ret_key); generator->key = ret_key; } if(cxt->function->return_variable->address) { if(!qb_transfer_value_to_zval(cxt->function->local_storage, cxt->function->return_variable->address, ret)) { uint32_t line_id = qb_get_zend_line_id(TSRMLS_C); qb_append_exception_variable_name(cxt->function->return_variable TSRMLS_CC); qb_set_exception_line_id(line_id TSRMLS_CC); return FALSE; } } if(cxt->function->return_key_variable->address) { if(!qb_transfer_value_to_zval(cxt->function->local_storage, cxt->function->return_key_variable->address, ret_key)) { uint32_t line_id = qb_get_zend_line_id(TSRMLS_C); qb_append_exception_variable_name(cxt->function->return_key_variable TSRMLS_CC); qb_set_exception_line_id(line_id TSRMLS_CC); return FALSE; } } if(cxt->function->sent_variable->address) { #if PHP_MINOR_VERSION > 5 || PHP_RELEASE_VERSION > 7 static zval _dummy_value, *dummy_value = &_dummy_value; if(generator->send_target) { zval_ptr_dtor(generator->send_target); } generator->send_target = (zval **) &cxt->send_target; // Zend will call Z_DELREF_PP() on what generator->send_target points to // put a dummy value there so it doesn't crash *generator->send_target = dummy_value; #else if(!generator->send_target) { cxt->send_target = emalloc(sizeof(temp_variable)); memset(cxt->send_target, 0, sizeof(temp_variable)); generator->send_target = cxt->send_target; } #endif } return TRUE; }
static int32_t qb_transfer_arguments_to_php(qb_interpreter_context *cxt) { USE_TSRM #if !ZEND_ENGINE_2_2 && !ZEND_ENGINE_2_1 void **p = EG(current_execute_data)->prev_execute_data->function_state.arguments; #else void **p = EG(argument_stack).top_element-1-1; #endif uint32_t received_argument_count = (uint32_t) (uintptr_t) *p; uint32_t i; // copy changes to by-ref arguments for(i = 0; i < cxt->function->argument_count; i++) { qb_variable *qvar = cxt->function->variables[i]; if(qvar->flags & QB_VARIABLE_BY_REF) { if(i < received_argument_count) { zval **p_zarg = (zval**) p - received_argument_count + i; zval *zarg = *p_zarg; if(!qb_transfer_value_to_zval(cxt->function->local_storage, qvar->address, zarg)) { uint32_t line_id = qb_get_zend_line_id(TSRMLS_C); qb_append_exception_variable_name(qvar TSRMLS_CC); qb_set_exception_line_id(line_id TSRMLS_CC); return FALSE; } } } qvar->value = NULL; } if(EG(return_value_ptr_ptr)) { // copy value into return variable zval *ret, **p_ret = EG(return_value_ptr_ptr); ALLOC_INIT_ZVAL(ret); *p_ret = ret; if(cxt->function->return_variable->address) { if(!qb_transfer_value_to_zval(cxt->function->local_storage, cxt->function->return_variable->address, ret)) { uint32_t line_id = qb_get_zend_line_id(TSRMLS_C); qb_append_exception_variable_name(cxt->function->return_variable TSRMLS_CC); qb_set_exception_line_id(line_id TSRMLS_CC); return FALSE; } } } return TRUE; }
static int32_t qb_transfer_value_to_import_source(qb_interpreter_context *cxt, qb_variable *ivar, qb_import_scope *scope) { int32_t result = TRUE; if(ivar->flags & QB_VARIABLE_IMPORTED) { USE_TSRM zval *zvalue = ivar->value, **p_zvalue = ivar->value_pointer; if(!IS_READ_ONLY(ivar->address)) { if(zvalue) { // separate the zval first, since we're modifying it SEPARATE_ZVAL_IF_NOT_REF(&zvalue); } else { ALLOC_INIT_ZVAL(zvalue); } if(!qb_transfer_value_to_zval(scope->storage, ivar->address, zvalue)) { uint32_t line_id = qb_get_zend_line_id(TSRMLS_C); qb_append_exception_variable_name(ivar TSRMLS_CC); qb_set_exception_line_id(line_id TSRMLS_CC); result = FALSE; } if(p_zvalue) { *p_zvalue = zvalue; } else { if(ivar->flags & QB_VARIABLE_GLOBAL) { zend_hash_quick_update(&EG(symbol_table), ivar->name, ivar->name_length + 1, ivar->hash_value, (void **) &zvalue, sizeof(zval *), NULL); } else if(ivar->flags & QB_VARIABLE_CLASS_INSTANCE) { zval *container = scope->object; zval *name = qb_string_to_zval(ivar->name, ivar->name_length TSRMLS_CC); Z_OBJ_WRITE_PROP(container, name, zvalue); } } } if(!p_zvalue && zvalue) { // if p_zvalue isn't null, then something else has put a refcount // on the zval (and we didn't increment it earlier) zval_ptr_dtor(&zvalue); } ivar->value_pointer = NULL; ivar->value = NULL; ivar->flags &= ~QB_VARIABLE_IMPORTED; } return result; }
static int32_t qb_transfer_value_to_import_source(qb_interpreter_context *cxt, qb_variable *ivar, qb_import_scope *scope) { int32_t result = TRUE; if(ivar->flags & QB_VARIABLE_IMPORTED) { USE_TSRM if(!READ_ONLY(ivar->address)) { zval *zvalue; if(ivar->value_pointer) { zvalue = *ivar->value_pointer; } else { zvalue = ivar->value; // separate the zval first, since we're modifying it SEPARATE_ZVAL_TO_MAKE_IS_REF(&zvalue); } if(!zvalue) { ALLOC_INIT_ZVAL(zvalue); if(ivar->value_pointer) { *ivar->value_pointer = zvalue; } } if(!qb_transfer_value_to_zval(scope->storage, ivar->address, zvalue)) { uint32_t line_id = qb_get_zend_line_id(TSRMLS_C); qb_set_exception_line_id(line_id TSRMLS_CC); result = FALSE; } if(!ivar->value_pointer) { if(ivar->flags & QB_VARIABLE_GLOBAL) { zend_hash_quick_update(&EG(symbol_table), ivar->name, ivar->name_length + 1, ivar->hash_value, (void **) &zvalue, sizeof(zval *), NULL); } else if(ivar->flags & QB_VARIABLE_CLASS_INSTANCE) { zval *container = scope->zend_object; zval *name = qb_string_to_zval(ivar->name, ivar->name_length TSRMLS_CC); Z_OBJ_WRITE_PROP(container, name, zvalue); zval_ptr_dtor(&zvalue); } } ivar->value_pointer = NULL; ivar->value = NULL; } ivar->flags &= ~QB_VARIABLE_IMPORTED; }