Example #1
0
int uopz_constant_handler(UOPZ_OPCODE_HANDLER_ARGS) { /* {{{ */
#if PHP_VERSION_ID >= 70100
	if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(EX(opline)->op2)))) {
		CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(EX(opline)->op2)), NULL);
	}
#else
	if (EX(opline)->op1_type == IS_UNUSED) {
		if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(EX(opline)->op2)))) {
			CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(EX(opline)->op2)), NULL);
		}
	} else {
		zend_string *key = NULL;
		zval *mock = NULL;
		zend_class_entry *poser = NULL;

		if (EX(opline)->op1_type == IS_CONST) {
			key = zend_string_tolower(Z_STR_P(EX_CONSTANT(EX(opline)->op1)));			

			if ((mock = zend_hash_find(&UOPZ(mocks), key))) {
				if (Z_TYPE_P(mock) == IS_OBJECT) {
					poser = Z_OBJCE_P(mock);
				} else poser = zend_lookup_class(Z_STR_P(mock));
				CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(EX(opline)->op1)), poser);
			}

			if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(EX(opline)->op2)))) {
				CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(EX(opline)->op2)), NULL);
			}

			zend_string_release(key);		
		} else {
			key = zend_string_tolower(Z_CE_P(EX_VAR(EX(opline)->op1.var))->name);
			
			if ((mock = zend_hash_find(&UOPZ(mocks), key))) {
				if (Z_TYPE_P(mock) == IS_OBJECT) {
					poser = Z_OBJCE_P(mock);
				} else poser = zend_lookup_class(Z_STR_P(mock));

				Z_CE_P(EX_VAR(EX(opline)->op1.var)) = poser;
			}

			CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(EX(opline)->op2)), 
								  Z_CE_P(EX_VAR(EX(opline)->op1.var)), NULL);

			zend_string_release(key);
		}
	}
#endif

	if (uopz_fetch_constant_handler) {
		return uopz_fetch_constant_handler(UOPZ_OPCODE_HANDLER_ARGS_PASSTHRU);
	}

	return ZEND_USER_OPCODE_DISPATCH;
} /* }}} */
Example #2
0
static void zend_generator_cleanup_unfinished_execution(zend_generator *generator) /* {{{ */
{
	zend_execute_data *execute_data = generator->execute_data;
	zend_op_array *op_array = &execute_data->func->op_array;

	if (generator->send_target) {
		if (Z_REFCOUNTED_P(generator->send_target)) Z_DELREF_P(generator->send_target);
		generator->send_target = NULL;
	}

	/* Manually free loop variables, as execution couldn't reach their
	 * SWITCH_FREE / FREE opcodes. */
	{
		/* -1 required because we want the last run opcode, not the
		 * next to-be-run one. */
		uint32_t op_num = execute_data->opline - op_array->opcodes - 1;

		int i;
		for (i = 0; i < op_array->last_brk_cont; ++i) {
			zend_brk_cont_element *brk_cont = op_array->brk_cont_array + i;

			if (brk_cont->start < 0) {
				continue;
			} else if ((uint32_t)brk_cont->start > op_num) {
				break;
			} else if (brk_cont->brk >= 0 && (uint32_t)brk_cont->brk > op_num) {
				zend_op *brk_opline = op_array->opcodes + brk_cont->brk;

				if (brk_opline->opcode == ZEND_FREE) {
					zval *var = EX_VAR(brk_opline->op1.var);
					zval_ptr_dtor_nogc(var);
				} else if (brk_opline->opcode == ZEND_FE_FREE) {
					zval *var = EX_VAR(brk_opline->op1.var);
					if (Z_TYPE_P(var) != IS_ARRAY && Z_FE_ITER_P(var) != (uint32_t)-1) {
						zend_hash_iterator_del(Z_FE_ITER_P(var));
					}
					zval_ptr_dtor_nogc(var);
				}
			}
		}
	}

	/* If yield was used as a function argument there may be active
	 * method calls those objects need to be freed */
	while (execute_data->call) {
		if (Z_OBJ(execute_data->call->This)) {
			OBJ_RELEASE(Z_OBJ(execute_data->call->This));
		}
		execute_data->call = execute_data->call->prev_execute_data;
	}
}
static zval *get_zval_ptr_safe(
	int op_type, const znode_op *node, const zend_execute_data *execute_data
) {
#ifdef ZEND_ENGINE_3
	switch (op_type) {
		case IS_CONST:
			return EX_CONSTANT(*node);
		case IS_CV:
		case IS_TMP_VAR:
		case IS_VAR:
		{
			zval *zv = EX_VAR(node->var);
			ZVAL_DEREF(zv);
			return !Z_ISUNDEF_P(zv) ? zv : NULL;
		}
		default:
			return NULL;
	}
#else
	switch (op_type) {
		case IS_CONST:
			return node->zv;
		case IS_TMP_VAR:
			return &SO_EX_T(node->var).tmp_var;
		case IS_VAR:
			return SO_EX_T(node->var).var.ptr;
		case IS_CV: {
			zval **tmp = SO_EX_CV(node->constant);
			return tmp ? *tmp : NULL;
		}
		default:
			return NULL;
	}
#endif
}
Example #4
0
static zval *smd_get_zval_ptr_cv(zend_execute_data *execute_data, uint32_t var, int type, int force_ret) /* {{{ */ {
    zval *ret = EX_VAR(var);

    if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
        if (force_ret) {
            switch (type) {
                case BP_VAR_R:
                case BP_VAR_UNSET:
                    zend_error(E_NOTICE, "Undefined variable: %s", ZSTR_VAL(CV_DEF_OF(EX_VAR_TO_NUM(var))));
                case BP_VAR_IS:
                    ret = &EG(uninitialized_zval);
                    break;
                case BP_VAR_RW:
                    zend_error(E_NOTICE, "Undefined variable: %s", ZSTR_VAL(CV_DEF_OF(EX_VAR_TO_NUM(var))));
                case BP_VAR_W:
                    ZVAL_NULL(ret);
                    break;
            }
        } else {
            return NULL;
        }
    } else {
        ZVAL_DEREF(ret);
    }
    return ret;
} /* }}} */
Example #5
0
/* {{{ */
static int php_memoize_return(zend_execute_data *execute_data) {
	zend_long ttl = 0;
	const zend_function *fbc = EX(func);

	if (MG(ini.enabled) && php_memoize_is_memoizing(fbc, &ttl)) {
		zend_string *key = php_memoize_key(
			&EX(This),
			fbc, EX_NUM_ARGS(), EX_VAR_NUM(0));

		if (key) {
			zval *return_value;

			if (EX(opline)->op1_type & IS_CONST) {
				return_value = EX_CONSTANT(EX(opline)->op1);
			} else {
				return_value = EX_VAR(EX(opline)->op1.var);
			}

			apc_cache_store(php_memoize_cache, key, return_value, ttl, 1);

			if (EG(exception)) {
				zend_clear_exception();
			}

			zend_string_release(key);
		}
	}
	
	if (zend_return_function) {
		return zend_return_function(execute_data);
	}

	return ZEND_USER_OPCODE_DISPATCH;
} /* }}} */
Example #6
0
/* {{{ */
static inline zend_bool php_memoize_is_memoized(const zend_execute_data *execute_data) {
	const zend_execute_data *call = EX(call);
	const zend_function *fbc = call->func;

	if (call && php_memoize_is_memoizing(fbc, NULL)) {
		zend_string *key = php_memoize_key(
			&call->This,
			fbc,
			ZEND_CALL_NUM_ARGS(call), ZEND_CALL_ARG(call, 1));
		zval *return_value;

		if (!key) {
			return 0;
		}

		return_value = EX_VAR(EX(opline)->result.var);

		if (apc_cache_fetch(php_memoize_cache, key, php_memoize_time(), &return_value)) {
			zend_string_release(key);
			return 1;
		}

		zend_string_release(key);
	}

	return 0;
} /* }}} */
Example #7
0
static zval *smd_get_zval_ptr_tmpvar(zend_execute_data *execute_data, uint32_t var, zend_free_op *should_free) /* {{{ */ {
    zval *ret = EX_VAR(var);

    if (should_free) {
        *should_free = ret;
    }
    ZVAL_DEREF(ret);

    return ret;
} /* }}} */
static int coro_exit_handler(zend_execute_data *execute_data)
{
    zval ex;
    zend_object *obj;
    zend_long flags = 0;
    if (sw_get_current_cid() != -1)
    {
        flags |= SW_EXIT_IN_COROUTINE;
    }
    if (SwooleG.serv && SwooleG.serv->gs->start)
    {
        flags |= SW_EXIT_IN_SERVER;
    }
    if (flags)
    {
        const zend_op *opline = EX(opline);
        zval _exit_status;
        zval *exit_status = NULL;

        if (opline->op1_type != IS_UNUSED)
        {
            if (opline->op1_type == IS_CONST)
            {
                // see: https://github.com/php/php-src/commit/e70618aff6f447a298605d07648f2ce9e5a284f5
#ifdef EX_CONSTANT
                exit_status = EX_CONSTANT(opline->op1);
#else
                exit_status = RT_CONSTANT(opline, opline->op1);
#endif
            }
            else
            {
                exit_status = EX_VAR(opline->op1.var);
            }
            if (Z_ISREF_P(exit_status))
            {
                exit_status = Z_REFVAL_P(exit_status);
            }
        }
        else
        {
            exit_status = &_exit_status;
            ZVAL_NULL(exit_status);
        }
        obj = zend_throw_error_exception(swoole_exit_exception_class_entry_ptr, "swoole exit.", 0, E_ERROR TSRMLS_CC);
        ZVAL_OBJ(&ex, obj);
        zend_update_property_long(swoole_exit_exception_class_entry_ptr, &ex, ZEND_STRL("flags"), flags);
        Z_TRY_ADDREF_P(exit_status);
        zend_update_property(swoole_exit_exception_class_entry_ptr, &ex, ZEND_STRL("status"), exit_status);
    }

    return ZEND_USER_OPCODE_DISPATCH;
}
Example #9
0
int uopz_return_handler(UOPZ_OPCODE_HANDLER_ARGS) { /* {{{ */
	zend_execute_data *call = EX(call);

	if (call) {
		uopz_return_t *ureturn;

		uopz_run_hook(call->func, call);

		ureturn = uopz_find_return(call->func);

		if (ureturn) {
			const zend_op *opline = EX(opline);
			zval rv, *return_value = RETURN_VALUE_USED(opline) ? 
				EX_VAR(EX(opline)->result.var) : &rv;

			if (UOPZ_RETURN_IS_EXECUTABLE(ureturn)) {
				if (UOPZ_RETURN_IS_BUSY(ureturn)) {
					goto _uopz_return_handler_dispatch;
				}

				uopz_execute_return(ureturn, call, return_value);

				if (!RETURN_VALUE_USED(opline)) {
					zval_ptr_dtor(&rv);
				}

				return php_uopz_leave_helper(UOPZ_OPCODE_HANDLER_ARGS_PASSTHRU);
			}

			if (RETURN_VALUE_USED(opline)) {
				ZVAL_COPY(return_value, &ureturn->value);
			}

			return php_uopz_leave_helper(UOPZ_OPCODE_HANDLER_ARGS_PASSTHRU);
		}
	}

_uopz_return_handler_dispatch:
	if (uopz_do_fcall_handler) {
		return uopz_do_fcall_handler(UOPZ_OPCODE_HANDLER_ARGS_PASSTHRU);
	}

	return ZEND_USER_OPCODE_DISPATCH;
} /* }}} */
Example #10
0
int uopz_no_exit_handler(UOPZ_OPCODE_HANDLER_ARGS) { /* {{{ */
	if (UOPZ(exit)) {
		if (uopz_exit_handler)
			return uopz_exit_handler(UOPZ_OPCODE_HANDLER_ARGS_PASSTHRU);

		return ZEND_USER_OPCODE_DISPATCH;
	}

	if (EX(opline)->op1_type != IS_UNUSED) {
		zval *estatus;

		if (EX(opline)->op1_type == IS_CONST) {
			estatus = EX_CONSTANT(EX(opline)->op1);
		} else estatus = EX_VAR(EX(opline)->op1.var);

		if (Z_ISREF_P(estatus)) {
			estatus = Z_REFVAL_P(estatus);
		}

		if (Z_TYPE_P(estatus) == IS_LONG) {
			EG(exit_status) = Z_LVAL_P(estatus);
		} else EG(exit_status) = 0;

		ZVAL_COPY(&UOPZ(estatus), estatus);
	}

	if (EX(opline) < &EX(func)->op_array.opcodes[EX(func)->op_array.last - 1]) {
		EX(opline)++;

		while (EX(opline)->opcode == ZEND_EXT_STMT) {
			EX(opline)++;
		}

		return ZEND_USER_OPCODE_CONTINUE;
	} else {
		return ZEND_USER_OPCODE_RETURN;
	}
} /* }}} */
ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_nested_func_helper(uint32_t call_info EXECUTE_DATA_DC)
{
	zend_execute_data *old_execute_data;

	if (UNEXPECTED(call_info & ZEND_CALL_HAS_SYMBOL_TABLE)) {
		zend_clean_and_cache_symbol_table(EX(symbol_table));
	}
	EG(current_execute_data) = EX(prev_execute_data);
	if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) {
		OBJ_RELEASE(Z_OBJ(execute_data->This));
	} else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
		OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func)));
	}

	zend_vm_stack_free_extra_args_ex(call_info, execute_data);
	old_execute_data = execute_data;
	execute_data = EX(prev_execute_data);
	zend_vm_stack_free_call_frame_ex(call_info, old_execute_data);

	if (UNEXPECTED(EG(exception) != NULL)) {
		const zend_op *old_opline = EX(opline);
		zend_throw_exception_internal(NULL);
		if (old_opline->result_type != IS_UNDEF) {
			zval_ptr_dtor(EX_VAR(old_opline->result.var));
		}
#ifndef HAVE_GCC_GLOBAL_REGS
		return 2; // ZEND_VM_LEAVE
#endif
	} else {
		EX(opline)++;
#ifdef HAVE_GCC_GLOBAL_REGS
		opline = EX(opline);
#else
		return 2; // ZEND_VM_LEAVE
#endif
	}
}
Example #12
0
int uopz_fetch_handler(UOPZ_OPCODE_HANDLER_ARGS) { /* {{{ */
	zval *name = NULL;
	zend_string *key = NULL;
	int UOPZ_VM_ACTION = ZEND_USER_OPCODE_DISPATCH;

	do {
		if (EX(opline)->op2_type == IS_UNUSED) {
			break;
		}
		
		if (EX(opline)->op2_type == IS_CONST) {
			name = 
				EX_CONSTANT(EX(opline)->op2);
			if (name) {
				key = Z_STR_P(name);
			}			
		} else if (EX(opline)->op2_type != IS_UNUSED) {
			name = EX_VAR(EX(opline)->op2.var);
			if (Z_TYPE_P(name) == IS_STRING) {
				key = Z_STR_P(name);
			} else if (Z_TYPE_P(name) == IS_OBJECT) {
				key = Z_OBJCE_P(name)->name;
			} else {
				
			}
		}

		if (key) {
			zval *mock = NULL;
			zend_class_entry *ce = NULL;
			zend_string *lookup = zend_string_tolower(key);

			if (UNEXPECTED((mock = zend_hash_find(&UOPZ(mocks), lookup)))) {

				switch (Z_TYPE_P(mock)) {
					case IS_OBJECT: ce = Z_OBJCE_P(mock); break;
					case IS_STRING: ce = zend_lookup_class(Z_STR_P(mock)); break;
				}

				if (ce) {
					if (EX(opline)->op2_type == IS_CONST) {
						CACHE_PTR(Z_CACHE_SLOT_P(name), ce);
					}

					Z_CE_P(EX_VAR(EX(opline)->result.var)) = ce;
					UOPZ_VM_ACTION = ZEND_USER_OPCODE_CONTINUE;
				}
			}

			zend_string_release(lookup);
		}
	} while(0);

	if (UOPZ_VM_ACTION == ZEND_USER_OPCODE_CONTINUE) {
		EX(opline) = EX(opline) + 1;
	} else {
		if (uopz_fetch_class_handler) {
			return uopz_fetch_class_handler(UOPZ_OPCODE_HANDLER_ARGS_PASSTHRU);
		}
	}

	return UOPZ_VM_ACTION;
} /* }}} */
Example #13
0
int uopz_mock_handler(UOPZ_OPCODE_HANDLER_ARGS) { /* {{{ */
	int UOPZ_VM_ACTION = ZEND_USER_OPCODE_DISPATCH;
	zend_string *key;
	zval *mock = NULL;
	zend_class_entry *ce;

	if (EX(opline)->op1_type == IS_CONST) {
		ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(EX(opline)->op1)));

		if (UNEXPECTED(ce == NULL)) {
			key = Z_STR_P(EX_CONSTANT(EX(opline)->op1));
		} else {
			key = ce->name;
		}

		key = zend_string_tolower(key);
	} else if(EX(opline)->op1_type == IS_UNUSED) {
		ce = zend_fetch_class(NULL, EX(opline)->op1.num);
		if (UNEXPECTED(ce == NULL)) {
			return UOPZ_VM_ACTION;
		}
		key = 
			zend_string_tolower(ce->name);
	} else {
		key = zend_string_tolower(
			Z_CE_P(EX_VAR(EX(opline)->op1.var))->name);
	}

	if (UNEXPECTED((mock = zend_hash_find(&UOPZ(mocks), key)))) {
		switch (Z_TYPE_P(mock)) {
			case IS_OBJECT:
				ZVAL_COPY(
					EX_VAR(EX(opline)->result.var), mock);
#if PHP_VERSION_ID < 70100
				EX(opline) = 
					OP_JMP_ADDR(EX(opline), EX(opline)->op2);
#else
				if (EX(opline)->extended_value == 0 && 
					(EX(opline)+1)->opcode == ZEND_DO_FCALL) {
					EX(opline) += 2;
				}
#endif
				UOPZ_VM_ACTION = ZEND_USER_OPCODE_CONTINUE;
			break;

			case IS_STRING:
				ce = zend_lookup_class(Z_STR_P(mock));
				if (EXPECTED(ce)) {
					if (EX(opline)->op1_type == IS_CONST) {
						CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(EX(opline)->op1)), ce);
					} else if (EX(opline)->op1_type != IS_UNUSED) {
						Z_CE_P(EX_VAR(EX(opline)->op1.var)) = ce;
					} else {
						/* oh dear, can't do what is requested */			
					}
					
				}
			break;
		}
	}

	zend_string_release(key);

	if (UOPZ_VM_ACTION == ZEND_USER_OPCODE_DISPATCH) {
		if (uopz_new_handler) {
			return uopz_new_handler(UOPZ_OPCODE_HANDLER_ARGS_PASSTHRU);
		}
	}

	return UOPZ_VM_ACTION;
} /* }}} */
Example #14
0
int uopz_call_handler(UOPZ_OPCODE_HANDLER_ARGS) { /* {{{ */
	switch (EX(opline)->opcode) {
		case ZEND_INIT_FCALL_BY_NAME:
		case ZEND_INIT_FCALL:
		case ZEND_INIT_NS_FCALL_BY_NAME: {
			zval *function_name = EX_CONSTANT(EX(opline)->op2);
			CACHE_PTR(Z_CACHE_SLOT_P(function_name), NULL);
		} break;

		case ZEND_INIT_METHOD_CALL: {
			if (EX(opline)->op2_type == IS_CONST) {
				zval *function_name = EX_CONSTANT(EX(opline)->op2);
				CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), NULL, NULL);
			}
		} break;

		case ZEND_INIT_STATIC_METHOD_CALL: {
			zend_class_entry *ce;
			zval *mock;
			zend_string *key = NULL;
			
			if (EX(opline)->op1_type == IS_CONST) {
				key = zend_string_tolower(Z_STR_P(EX_CONSTANT(EX(opline)->op1)));
			} else if (EX(opline)->op1_type != IS_UNUSED) 	{
				ce = Z_CE_P(EX_VAR(EX(opline)->op1.var));
				if (!ce) {
					break;
				}
				key = zend_string_tolower(ce->name);
			}

			if (key && (mock = zend_hash_find(&UOPZ(mocks), key))) {
				zend_class_entry *poser;

				if (Z_TYPE_P(mock) == IS_STRING) {
					poser = zend_lookup_class(Z_STR_P(mock));
					if (!poser) {
						break;
					}
				} else poser = Z_OBJCE_P(mock);

				if (EX(opline)->op1_type == IS_CONST) {
					CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(EX(opline)->op1)), poser);
				} else {
					Z_CE_P(EX_VAR(EX(opline)->op1.var)) = poser;
				}
			}

			if (key && EX(opline)->op2_type == IS_CONST) {
				zval *function_name = EX_CONSTANT(EX(opline)->op2);
				if (EX(opline)->op1_type == IS_CONST) {
					CACHE_PTR(Z_CACHE_SLOT_P(function_name), NULL);
				} else {
					CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), NULL, NULL);
				}
			}
			
			if (key) {
				zend_string_release(key);
			}
		} break;
	}

	switch (EX(opline)->opcode) {
		case ZEND_INIT_FCALL_BY_NAME:
			if (uopz_init_fcall_by_name_handler)
				return uopz_init_fcall_by_name_handler(UOPZ_OPCODE_HANDLER_ARGS_PASSTHRU);
		case ZEND_INIT_FCALL:
			if (uopz_init_fcall_handler)
				return uopz_init_fcall_handler(UOPZ_OPCODE_HANDLER_ARGS_PASSTHRU);
		case ZEND_INIT_NS_FCALL_BY_NAME:
			if (uopz_init_ns_fcall_by_name_handler)
				return uopz_init_ns_fcall_by_name_handler(UOPZ_OPCODE_HANDLER_ARGS_PASSTHRU);
		case ZEND_INIT_METHOD_CALL:
			if (uopz_init_method_call_handler)
				return uopz_init_method_call_handler(UOPZ_OPCODE_HANDLER_ARGS_PASSTHRU);
		case ZEND_INIT_STATIC_METHOD_CALL:
			if (uopz_init_static_method_call_handler)
				return uopz_init_static_method_call_handler(UOPZ_OPCODE_HANDLER_ARGS_PASSTHRU);
	}

	return ZEND_USER_OPCODE_DISPATCH;
} /* }}} */