コード例 #1
0
ファイル: qb_interpreter.c プロジェクト: 3CTO/qb
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;
}
コード例 #2
0
ファイル: qb_interpreter.c プロジェクト: 3CTO/qb
static int32_t qb_transfer_arguments_from_php(qb_interpreter_context *cxt) {
	USE_TSRM
	int32_t result = TRUE;
#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;

	for(i = 0; i < cxt->function->argument_count; i++) {
		qb_variable *qvar = cxt->function->variables[i];
		uint32_t transfer_flags = 0;
		if(qvar->flags & QB_VARIABLE_BY_REF) {
			// avoid allocating new memory and copying contents if changes will be copied back anyway
			transfer_flags = QB_TRANSFER_CAN_BORROW_MEMORY | QB_TRANSFER_CAN_AUTOVIVIFICATE;
		} else if(IS_READ_ONLY(qvar->address)) {
			// or if no changes will be made
			transfer_flags = QB_TRANSFER_CAN_BORROW_MEMORY;
		}

		if(i < received_argument_count) {
			zval **p_zarg = (zval**) p - received_argument_count + i;
			zval *zarg = *p_zarg;
			if(!qb_transfer_value_from_zval(cxt->function->local_storage, qvar->address, zarg, transfer_flags)) {
				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);
				result = FALSE;
			}
			qvar->value = zarg;
		} else {
			if(qvar->default_value) {
				zval *zarg = qvar->default_value;
				if(!qb_transfer_value_from_zval(cxt->function->local_storage, qvar->address, zarg, transfer_flags)) {
					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);
					result = FALSE;
				}
			} else {
				const char *class_name = (EG(active_op_array)->scope) ? EG(active_op_array)->scope->name : NULL;
				zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data;
				uint32_t caller_line_id = 0;
				if(ptr && ptr->op_array) {
					uint32_t caller_file_id = qb_get_source_file_id(ptr->op_array->filename TSRMLS_CC);
					uint32_t caller_line_number = ptr->opline->lineno;
					caller_line_id = LINE_ID(caller_file_id, caller_line_number);
				}
				qb_report_missing_argument_exception(cxt->function->line_id, class_name, cxt->function->name, i, caller_line_id);
			}
		}
	}
	return result;
}
コード例 #3
0
ファイル: qb_interpreter.c プロジェクト: 3CTO/qb
static int32_t qb_transfer_value_from_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 = NULL, **p_zvalue = NULL;
		switch(scope->type) {
			case QB_IMPORT_SCOPE_GLOBAL:
			case QB_IMPORT_SCOPE_LEXICAL: {
				// copy value from symbol table
				zend_hash_quick_find(scope->symbol_table, ivar->name, ivar->name_length + 1, ivar->hash_value, (void **) &p_zvalue);
			}	break;
			case QB_IMPORT_SCOPE_CLASS: {
				if(ivar->flags & QB_VARIABLE_CLASS_CONSTANT) {
					// static:: constants are treated like variables
					zend_class_entry *ce = scope->class_entry;
					zval **p_value;
					zend_hash_quick_find(&ce->constants_table, ivar->name, ivar->name_length + 1, ivar->hash_value, (void **) &p_value);
				} else {
					zend_class_entry *ce = scope->class_entry;
					p_zvalue = Z_CLASS_GET_PROP(ce, ivar->name, ivar->name_length);
				}
			}	break;
			case QB_IMPORT_SCOPE_OBJECT: {
				// copy value from class instance
				zval *name = qb_string_to_zval(ivar->name, ivar->name_length TSRMLS_CC);
				zval *container = scope->object;
				p_zvalue = Z_OBJ_GET_PROP_PTR_PTR(container, name);
				if(!p_zvalue) {
					if(Z_OBJ_HT_P(container)->read_property) {
						zvalue = Z_OBJ_READ_PROP(container, name);
					}
				}
			}	break;
			default: {
			}	break;
		}
		if(p_zvalue) {
			zvalue = *p_zvalue;
		}
		if(qb_transfer_value_from_zval(scope->storage, ivar->address, (zvalue) ? zvalue : &zval_used_for_init, QB_TRANSFER_CAN_BORROW_MEMORY | QB_TRANSFER_CAN_AUTOVIVIFICATE)) {
			ivar->flags |= QB_VARIABLE_IMPORTED;
			ivar->value_pointer = p_zvalue;
			ivar->value = zvalue;

			if(!p_zvalue && zvalue) {
				// we got the zval from a getter function
				// need to up the reference count
				Z_ADDREF_P(zvalue);
			}
		} else {
			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;
		}
	}
	return result;
}
コード例 #4
0
ファイル: qb_interpreter.c プロジェクト: 3CTO/qb
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;
}
コード例 #5
0
ファイル: qb_interpreter.c プロジェクト: 3CTO/qb
static int32_t qb_transfer_arguments_from_caller(qb_interpreter_context *cxt) {
	uint32_t received_argument_count = cxt->caller_context->argument_count;
	uint32_t i;
	for(i = 0; i < cxt->function->argument_count; i++) {
		qb_variable *qvar = cxt->function->variables[i];

		if(i < received_argument_count) {
			uint32_t argument_index = cxt->caller_context->argument_indices[i];
			qb_variable *caller_qvar = cxt->caller_context->function->variables[argument_index];
			qb_storage *caller_storage = cxt->caller_context->function->local_storage;
			uint32_t transfer_flags = 0;
			if((qvar->flags & QB_VARIABLE_BY_REF) || IS_READ_ONLY(qvar->address)) {
				transfer_flags = QB_TRANSFER_CAN_BORROW_MEMORY;
			}
			if(!qb_transfer_value_from_storage_location(cxt->function->local_storage, qvar->address, caller_storage, caller_qvar->address, transfer_flags)) {
				USE_TSRM
				qb_append_exception_variable_name(qvar TSRMLS_CC);
				qb_set_exception_line_id(cxt->caller_context->line_id TSRMLS_CC);
				return FALSE;
			}
		} else {
			if(qvar->default_value) {
				zval *zarg = qvar->default_value;
				uint32_t transfer_flags = 0;
				if(IS_READ_ONLY(qvar->address)) {
					transfer_flags = QB_TRANSFER_CAN_BORROW_MEMORY;
				}
				if(!qb_transfer_value_from_zval(cxt->function->local_storage, qvar->address, zarg, transfer_flags)) {
					USE_TSRM
					qb_append_exception_variable_name(qvar TSRMLS_CC);
					qb_set_exception_line_id(cxt->caller_context->line_id TSRMLS_CC);
					return FALSE;
				}
			} else {
				USE_TSRM
				const char *class_name = (EG(active_op_array)->scope) ? EG(active_op_array)->scope->name : NULL;
				qb_report_missing_argument_exception(cxt->function->line_id, class_name, cxt->function->name, i, cxt->caller_context->line_id);
			}
		}
	}
	return TRUE;
}
コード例 #6
0
ファイル: qb_interpreter.c プロジェクト: 3CTO/qb
static int32_t qb_transfer_arguments_to_caller(qb_interpreter_context *cxt) {
	uint32_t received_argument_count = cxt->caller_context->argument_count;
	uint32_t retval_index = cxt->caller_context->result_index;
	uint32_t i;
	for(i = 0; i < cxt->function->argument_count; i++) {
		qb_variable *qvar = cxt->function->variables[i];

		if(i < received_argument_count) {
			uint32_t argument_index = cxt->caller_context->argument_indices[i];
			qb_variable *caller_qvar = cxt->caller_context->function->variables[argument_index];
			qb_storage *caller_storage = cxt->caller_context->function->local_storage;
			if(qvar->flags & QB_VARIABLE_BY_REF) {
				if(!qb_transfer_value_to_storage_location(cxt->function->local_storage, qvar->address, caller_storage, caller_qvar->address)) {
					USE_TSRM
					qb_append_exception_variable_name(qvar TSRMLS_CC);
					qb_set_exception_line_id(cxt->caller_context->line_id TSRMLS_CC);
					return FALSE;
				}
			}
		}
	}

	if(retval_index != INVALID_INDEX) {
		if(cxt->function->return_variable->address) {
			qb_variable *qvar = cxt->function->return_variable;
			qb_variable *caller_qvar = cxt->caller_context->function->variables[retval_index];
			qb_storage *caller_storage = cxt->caller_context->function->local_storage;
			if(!qb_transfer_value_to_storage_location(cxt->function->local_storage, qvar->address, caller_storage, caller_qvar->address)) {
				USE_TSRM
				qb_append_exception_variable_name(qvar TSRMLS_CC);
				qb_set_exception_line_id(cxt->caller_context->line_id TSRMLS_CC);
				return FALSE;
			}
		}
	}
	return TRUE;
}
コード例 #7
0
ファイル: qb_interpreter.c プロジェクト: 3CTO/qb
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;
}
コード例 #8
0
ファイル: qb_interpreter.c プロジェクト: remicollet/qb
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;
	}