int main(int argc, char **argv){
	zend_op_array *op_array;
	zend_file_handle file_handle;

	if(argc != 2) {
		printf("usage:  op_dumper <php script>\n");
		return 1;
	}
	PHP_EMBED_START_BLOCK(argc, argv);
	printf("Script: %s\n", argv[1]);
	file_handle.filename = argv[1];
	file_handle.free_filename = 0;
	file_handle.type = ZEND_HANDLE_FILENAME;
	file_handle.opened_path = NULL;
	op_array =  zend_compile_file(&file_handle, ZEND_INCLUDE TSRMLS_CC);
	if(!op_array) {
		printf("Error parsing script: %s\n", file_handle.filename);
		return 1;
	}
	dump_op_array(op_array);
    destroy_op_array(op_array TSRMLS_CC);
    efree(op_array);
	PHP_EMBED_END_BLOCK();
	return 0;
}
Beispiel #2
0
static void zend_closure_free_storage(zend_object *object) /* {{{ */
{
	zend_closure *closure = (zend_closure *)object;

	zend_object_std_dtor(&closure->std);

	if (closure->func.type == ZEND_USER_FUNCTION) {
		zend_execute_data *ex = EG(current_execute_data);
		while (ex) {
			if (ex->func == &closure->func) {
				zend_error(E_ERROR, "Cannot destroy active lambda function");
			}
			ex = ex->prev_execute_data;
		}
		destroy_op_array(&closure->func.op_array);
	}

	if (closure->debug_info != NULL) {
		zend_hash_destroy(closure->debug_info);
		efree(closure->debug_info);
	}

	if (Z_TYPE(closure->this_ptr) != IS_UNDEF) {
		zval_ptr_dtor(&closure->this_ptr);
	}
}
Beispiel #3
0
static int spl_autoload(zend_string *class_name, zend_string *lc_name, const char *ext, int ext_len) /* {{{ */
{
	char *class_file;
	int class_file_len;
	zval dummy;
	zend_file_handle file_handle;
	zend_op_array *new_op_array;
	zval result;
	int ret;

	class_file_len = (int)spprintf(&class_file, 0, "%s%.*s", ZSTR_VAL(lc_name), ext_len, ext);

#if DEFAULT_SLASH != '\\'
	{
		char *ptr = class_file;
		char *end = ptr + class_file_len;

		while ((ptr = memchr(ptr, '\\', (end - ptr))) != NULL) {
			*ptr = DEFAULT_SLASH;
		}
	}
#endif

	ret = php_stream_open_for_zend_ex(class_file, &file_handle, USE_PATH|STREAM_OPEN_FOR_INCLUDE);

	if (ret == SUCCESS) {
		zend_string *opened_path;
		if (!file_handle.opened_path) {
			file_handle.opened_path = zend_string_init(class_file, class_file_len, 0);
		}
		opened_path = zend_string_copy(file_handle.opened_path);
		ZVAL_NULL(&dummy);
		if (zend_hash_add(&EG(included_files), opened_path, &dummy)) {
			new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE);
			zend_destroy_file_handle(&file_handle);
		} else {
			new_op_array = NULL;
			zend_file_handle_dtor(&file_handle);
		}
		zend_string_release(opened_path);
		if (new_op_array) {
			ZVAL_UNDEF(&result);
			zend_execute(new_op_array, &result);

			destroy_op_array(new_op_array);
			efree(new_op_array);
			if (!EG(exception)) {
				zval_ptr_dtor(&result);
			}

			efree(class_file);
			return zend_hash_exists(EG(class_table), lc_name);
		}
	}
	efree(class_file);
	return 0;
} /* }}} */
Beispiel #4
0
int  edge_file_include(char *file_path)
{
    //include file 操作,没有直接的zend_api函数,如果使用,则需要在php执行编译的opcode中操作
    //以下的代码借鉴了yaf框架里面的include逻辑
    zend_file_handle file_handle;
    zend_op_array   *op_array;
    file_handle.filename = file_path;
    file_handle.free_filename = 0;
    file_handle.type = ZEND_HANDLE_FILENAME;
    file_handle.opened_path = NULL;
    file_handle.handle.fp = NULL;
    op_array = zend_compile_file(&file_handle, ZEND_INCLUDE TSRMLS_CC);
    if (op_array && file_handle.handle.stream.handle) 
    {
        int dummy = 1;

        if (!file_handle.opened_path)
        {
            file_handle.opened_path = file_path;
        }   

        zend_hash_add(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path)+1, (void *)&dummy, sizeof(int), NULL);
    }   
    zend_destroy_file_handle(&file_handle TSRMLS_CC);

    if (op_array)
    {
        zval *result = NULL;
    
        EDGE_BYAF_STORE_EG_ENVIRON();

        EG(return_value_ptr_ptr) = &result;
        EG(active_op_array)      = op_array;
#if ((PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION > 2)) || (PHP_MAJOR_VERSION > 5)
        if (!EG(active_symbol_table)) 
        {
            zend_rebuild_symbol_table(TSRMLS_C);
        }
#endif
        zend_execute(op_array TSRMLS_CC);
        destroy_op_array(op_array TSRMLS_CC);
        efree(op_array);
        if (!EG(exception)) 
        {
            if (EG(return_value_ptr_ptr) && *EG(return_value_ptr_ptr)) 
            {
                zval_ptr_dtor(EG(return_value_ptr_ptr));
            }
        }

        EDGE_BYAF_RESTORE_EG_ENVIRON();
        return 1;
    }
    return 0;
}
Beispiel #5
0
static PHP_RSHUTDOWN_FUNCTION(phpdbg) /* {{{ */
{
	zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE]);
	zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM]);
	zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE]);
	zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE]);
	zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE]);
	zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE]);
	zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE]);
	zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD]);
	zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_COND]);
	zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP]);
	zend_hash_destroy(&PHPDBG_G(seek));
	zend_hash_destroy(&PHPDBG_G(registered));
	zend_hash_destroy(&PHPDBG_G(file_sources));
	zend_hash_destroy(&PHPDBG_G(watchpoints));
	zend_llist_destroy(&PHPDBG_G(watchlist_mem));

	if (PHPDBG_G(buffer)) {
		efree(PHPDBG_G(buffer));
		PHPDBG_G(buffer) = NULL;
	}

	if (PHPDBG_G(exec)) {
		efree(PHPDBG_G(exec));
		PHPDBG_G(exec) = NULL;
	}

	if (PHPDBG_G(prompt)[0]) {
		free(PHPDBG_G(prompt)[0]);
	}
	if (PHPDBG_G(prompt)[1]) {
		free(PHPDBG_G(prompt)[1]);
	}

	PHPDBG_G(prompt)[0] = NULL;
	PHPDBG_G(prompt)[1] = NULL;

	if (PHPDBG_G(oplog)) {
		fclose(
				PHPDBG_G(oplog));
		PHPDBG_G(oplog) = NULL;
	}

	if (PHPDBG_G(ops)) {
		destroy_op_array(PHPDBG_G(ops) TSRMLS_CC);
		efree(PHPDBG_G(ops));
		PHPDBG_G(ops) = NULL;
	}

	return SUCCESS;
} /* }}} */
Beispiel #6
0
ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished_execution) /* {{{ */
{
	if (Z_TYPE(generator->value) != IS_UNDEF) {
		zval_ptr_dtor(&generator->value);
		ZVAL_UNDEF(&generator->value);
	}

	if (Z_TYPE(generator->key) != IS_UNDEF) {
		zval_ptr_dtor(&generator->key);
		ZVAL_UNDEF(&generator->key);
	}

	if (generator->execute_data) {
		zend_execute_data *execute_data = generator->execute_data;
		zend_op_array *op_array = &execute_data->func->op_array;

		if (!execute_data->symbol_table) {
			zend_free_compiled_variables(execute_data);
		} else {
			zend_clean_and_cache_symbol_table(execute_data->symbol_table);
		}

		if (Z_OBJ(execute_data->This)) {
			OBJ_RELEASE(Z_OBJ(execute_data->This));
		}

		/* A fatal error / die occurred during the generator execution. Trying to clean
		 * up the stack may not be safe in this case. */
		if (CG(unclean_shutdown)) {
			generator->execute_data = NULL;
			return;
		}

		zend_vm_stack_free_extra_args(generator->execute_data);

		/* Some cleanups are only necessary if the generator was closued
		 * before it could finish execution (reach a return statement). */
		if (!finished_execution) {
			zend_generator_cleanup_unfinished_execution(generator);
		}

		/* Free a clone of closure */
		if (op_array->fn_flags & ZEND_ACC_CLOSURE) {
			destroy_op_array(op_array);
			efree_size(op_array, sizeof(zend_op_array));
		}

		efree(generator->stack);
		generator->execute_data = NULL;
	}
}
Beispiel #7
0
static void zend_closure_free_storage(zend_object *object) /* {{{ */
{
    zend_closure *closure = (zend_closure *)object;

    zend_object_std_dtor(&closure->std);

    if (closure->func.type == ZEND_USER_FUNCTION) {
        destroy_op_array(&closure->func.op_array);
    }

    if (Z_TYPE(closure->this_ptr) != IS_UNDEF) {
        zval_ptr_dtor(&closure->this_ptr);
    }
}
Beispiel #8
0
static void php_phpdbg_destroy_bp_condition(void *data) /* {{{ */
{
	phpdbg_breakcond_t *brake = (phpdbg_breakcond_t*) data;

	if (brake) {
		if (brake->ops) {
			TSRMLS_FETCH();

			destroy_op_array(
					brake->ops TSRMLS_CC);
			efree(brake->ops);
		}
		efree((char*)brake->code);
	}
} /* }}} */
Beispiel #9
0
static void zend_closure_free_storage(zend_object *object) /* {{{ */
{
	zend_closure *closure = (zend_closure *)object;

	zend_object_std_dtor(&closure->std);

	if (closure->func.type == ZEND_USER_FUNCTION) {
		if (closure->func.op_array.fn_flags & ZEND_ACC_NO_RT_ARENA) {
			efree(closure->func.op_array.run_time_cache);
			closure->func.op_array.run_time_cache = NULL;
		}
		destroy_op_array(&closure->func.op_array);
	}

	if (Z_TYPE(closure->this_ptr) != IS_UNDEF) {
		zval_ptr_dtor(&closure->this_ptr);
	}
}
static ZEND_FUNCTION(opcache_compile_file)
{
	char *script_name;
	size_t script_name_len;
	zend_file_handle handle;
	zend_op_array *op_array = NULL;
	zend_execute_data *orig_execute_data = NULL;

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &script_name, &script_name_len) == FAILURE) {
		return;
	}

	if (!ZCG(enabled) || !accel_startup_ok || !ZCSG(accelerator_enabled)) {
		zend_error(E_NOTICE, ACCELERATOR_PRODUCT_NAME " seems to be disabled, can't compile file");
		RETURN_FALSE;
	}

	handle.filename = script_name;
	handle.free_filename = 0;
	handle.opened_path = NULL;
	handle.type = ZEND_HANDLE_FILENAME;

	orig_execute_data = EG(current_execute_data);

	zend_try {
		op_array = persistent_compile_file(&handle, ZEND_INCLUDE);
	} zend_catch {
		EG(current_execute_data) = orig_execute_data;
		zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME " could not compile file %s", handle.filename);
	} zend_end_try();

	if(op_array != NULL) {
		destroy_op_array(op_array);
		efree(op_array);
		RETVAL_TRUE;
	} else {
		RETVAL_FALSE;
	}
	zend_destroy_file_handle(&handle);
}
Beispiel #11
0
ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished_execution TSRMLS_DC) /* {{{ */
{
	if (generator->value) {
		zval_ptr_dtor(&generator->value);
		generator->value = NULL;
	}

	if (generator->key) {
		zval_ptr_dtor(&generator->key);
		generator->key = NULL;
	}

	if (generator->execute_data) {
		zend_execute_data *execute_data = generator->execute_data;
		zend_op_array *op_array = execute_data->op_array;

		if (!execute_data->symbol_table) {
			zend_free_compiled_variables(execute_data);
		} else {
			zend_clean_and_cache_symbol_table(execute_data->symbol_table TSRMLS_CC);
		}

		if (execute_data->current_this) {
			zval_ptr_dtor(&execute_data->current_this);
		}

		/* A fatal error / die occured during the generator execution. Trying to clean
		 * up the stack may not be safe in this case. */
		if (CG(unclean_shutdown)) {
			return;
		}

		/* If the generator is closed before it can finish execution (reach
		 * a return statement) we have to free loop variables manually, as
		 * we don't know whether the SWITCH_FREE / FREE opcodes have run */
		if (!finished_execution) {
			/* -1 required because we want the last run opcode, not the
			 * next to-be-run one. */
			zend_uint 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 (brk_cont->start > op_num) {
					break;
				} else if (brk_cont->brk > op_num) {
					zend_op *brk_opline = op_array->opcodes + brk_cont->brk;

					switch (brk_opline->opcode) {
						case ZEND_SWITCH_FREE:
							{
								temp_variable *var = EX_TMP_VAR(execute_data, brk_opline->op1.var);
								zval_ptr_dtor(&var->var.ptr);
							}
							break;
						case ZEND_FREE:
							{
								temp_variable *var = EX_TMP_VAR(execute_data, brk_opline->op1.var);
								zval_dtor(&var->tmp_var);
							}
							break;
					}
				}
			}
		}

		/* Clear any backed up stack arguments */
		if (generator->stack != EG(argument_stack)) {
			void **ptr = generator->stack->top - 1;
			void **end = zend_vm_stack_frame_base(execute_data);

			/* If the top stack element is the argument count, skip it */
			if (execute_data->function_state.arguments) {
				ptr--;
			}

			for (; ptr >= end; --ptr) {
				zval_ptr_dtor((zval**) ptr);
			}
		}

		while (execute_data->call >= execute_data->call_slots) {
			if (execute_data->call->object) {
				zval_ptr_dtor(&execute_data->call->object);
			}
			execute_data->call--;
		}

		/* We have added an additional stack frame in prev_execute_data, so we
		 * have to free it. It also contains the arguments passed to the
		 * generator (for func_get_args) so those have to be freed too. */
		{
			zend_execute_data *prev_execute_data = execute_data->prev_execute_data;
			void **arguments = prev_execute_data->function_state.arguments;

			if (arguments) {
				int arguments_count = (int) (zend_uintptr_t) *arguments;
				zval **arguments_start = (zval **) (arguments - arguments_count);
				int i;

				for (i = 0; i < arguments_count; ++i) {
					zval_ptr_dtor(arguments_start + i);
				}
			}
		}

		/* Free a clone of closure */
		if (op_array->fn_flags & ZEND_ACC_CLOSURE) {
			destroy_op_array(op_array TSRMLS_CC);
			efree(op_array);
		}

		efree(generator->stack);
		if (generator->stack == EG(argument_stack)) {
			/* abnormal exit for running generator */
			EG(argument_stack) = NULL;
		}
		generator->execute_data = NULL;
	}
}
/* {{{ CompiledScript compile(String source) */
JNIEXPORT jobject JNICALL Java_CompiledScript_call(JNIEnv *env, jobject object, jobject self, jstring method, jobjectArray args) {
	TSRMLS_FETCH();
    
    const char *methodName= (*env)->GetStringUTFChars(env, method, 0);
    jclass cls = (*env)->GetObjectClass(env, object);
    jfieldID oparrayField = (*env)->GetFieldID(env, cls, "oparrayptr", "Ljava/nio/ByteBuffer;");
    
    zend_op_array *compiled_op_array= (zend_op_array*)((*env)->GetDirectBufferAddress(
        env, 
        (*env)->GetObjectField(env, object, oparrayField)
    ));
    
    /* DEBUG printf("CompiledScript.call({object}, %s, args[]) op_array = %p\n", methodName, compiled_op_array); */
    
    if (compiled_op_array) {
        zend_first_try {
            zend_llist global_vars;
            zend_llist_init(&global_vars, sizeof(char *), NULL, 0);

            zval *local_retval_ptr= NULL;

            EG(return_value_ptr_ptr)= &local_retval_ptr;
		    EG(active_op_array)= compiled_op_array;
		    EG(no_extensions)= 1;

            jint arg_count= (*env)->GetArrayLength(env, args);
            zval function;
            
            function.value.str.val= estrdup(methodName);
            function.value.str.len= strlen(methodName);
            function.type= IS_STRING;
            
            zval *retval_ptr= NULL;
            zval ***params= (zval ***)safe_emalloc(arg_count, sizeof(zval **), 0);
            
            jint i;
            for (i= 0; i < arg_count; i++) {
                params[i]= (zval**)emalloc(sizeof(zval **));
                
                ALLOC_ZVAL(*(params[i]));
                JObjectToZval(env, (*env)->GetObjectArrayElement(env, args, i), params[i]);
                INIT_PZVAL(*(params[i]));
            }
            
            if (FAILURE == call_user_function_ex(
                CG(function_table), 
                NULL, 
                &function, 
                &retval_ptr, 
                arg_count, 
                params, 
                1, 
                NULL TSRMLS_CC
            )) {
                printf("*** Calling %s() failed\n", methodName);
            }

            zval_dtor(&function);
            efree(params);

            EG(no_extensions)= 0;
		    destroy_op_array(compiled_op_array);
            EG(active_op_array)= NULL;

            zend_llist_destroy(&global_vars);
        } zend_catch {
            throw(env, "java/lang/IllegalArgumentException", "Bailout");
        } zend_end_try();
    }
    
    (*env)->ReleaseStringUTFChars(env, method, methodName);
    
    return;
}
Beispiel #13
0
ZEND_METHOD(afk_app, run){/*{{{*/
	zval **uri;
	char *c=NULL, *a=NULL;
	zval *arr = PG(http_globals)[TRACK_VARS_GET];
	//从http_globals中寻找get参数,确认Controller和action的值。
	if(arr && Z_TYPE_P(arr) == IS_ARRAY){
		if(zend_hash_find(HASH_OF(arr), HTTP_CONTRONLLER_PARAM, strlen(HTTP_CONTRONLLER_PARAM)+1, (void **)&uri) == SUCCESS){
			c = Z_STRVAL_PP(uri);
		}else{
			c = "index";
		}
		if(zend_hash_find(HASH_OF(arr), HTTP_ACTION_PARAM, strlen(HTTP_ACTION_PARAM)+1, (void **)&uri) == SUCCESS){
			a = Z_STRVAL_PP(uri);
		}else{
			a = "index";
		}
	}
	//寻找对应的Controller和action方法所在的文件。
	char *controller_path;
	spprintf(&controller_path, 0, "%s/controller/%s.php", APP_DIR, c);

	FILE *fp;
	//php_printf("%s\n", controller_path);
	//文件存在则引入该文件。不存在则报错。
	
	if( (fp = fopen(controller_path, "r")) != NULL){
		fclose(fp);
		int dummy = 1;

		zend_file_handle file_handle;
		zend_op_array *op_array;

		file_handle.filename = controller_path;
		file_handle.free_filename = 0;
		file_handle.type = ZEND_HANDLE_FILENAME;
		file_handle.opened_path = NULL;
		file_handle.handle.fp = NULL;

		op_array = zend_compile_file(&file_handle, ZEND_INCLUDE TSRMLS_CC);
		if (op_array && file_handle.handle.stream.handle) {
			int dummy = 1;         

			if (!file_handle.opened_path) {
				file_handle.opened_path = controller_path;
			}

			php_printf("opened_path: %s\n", file_handle.opened_path);
			zend_hash_add(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path)+1, (void *)&dummy, sizeof(int), NULL);
		}
		zend_destroy_file_handle(&file_handle TSRMLS_CC);
		if(op_array){
			php_printf("execute op_array \n");

			//保存旧的环境变量
			zval ** __old_return_value_pp   = EG(return_value_ptr_ptr); 
			zend_op ** __old_opline_ptr     = EG(opline_ptr); 
			zend_op_array * __old_op_array  = EG(active_op_array);
			zend_function_state * __old_func_state = EG(function_state_ptr); 

			//执行op_array
			zval *result = NULL;
			EG(return_value_ptr_ptr) = &result;
			EG(active_op_array) = op_array;
			zend_execute(op_array TSRMLS_CC);
			destroy_op_array(op_array TSRMLS_CC);
			efree(op_array);

			//恢复旧的环境变量
			EG(return_value_ptr_ptr) = __old_return_value_pp;
			EG(opline_ptr)           = __old_opline_ptr; 
			EG(active_op_array)      = __old_op_array; 
			EG(function_state_ptr)   = __old_func_state;
		}
	}else{
		char *error;
		spprintf(&error, 0, "cann't find file %s", controller_path);
		zend_error(1, error);
	}
	//dispatcher 调用分发的请求。
	/**
	 *在EG(class_table)查找相应的类,然后调用它的方法。
	 */
	zend_class_entry **class = NULL;
	char  *class_name = emalloc(strlen(c)+strlen("Controller")+1);
	class_name = strcpy(class_name, c);
	class_name = strcat(class_name, zend_str_tolower_dup("Controller", strlen("Controller")+1)); //Notice: class name need tolower.
	if(zend_hash_find(EG(class_table), class_name, strlen(class_name)+1, (void *)&class) != SUCCESS){
		char *error;
		spprintf(&error, 0, "cann't find the controller class: %s ", class_name);
		php_printf("%s", class_name);
		efree(class_name);
		efree(class);
		zend_error(1, error);
	}
	efree(class_name);

	zval *obj, *function_name, *retval;
	MAKE_STD_ZVAL(obj);
	MAKE_STD_ZVAL(function_name);
	MAKE_STD_ZVAL(retval);
	object_init_ex(obj, *class);
	//php_var_dump(&obj, 1 TSRMLS_CC);

	ZVAL_STRINGL(function_name, "indexaction", strlen("indexaction"), 1);
	call_user_function(&((*class)->function_table), &obj, function_name, retval, 0, NULL TSRMLS_CC);

	zval_ptr_dtor(&obj);
	zval_ptr_dtor(&function_name);
	zval_ptr_dtor(&retval);
	//efree(class);

	RETURN_BOOL(1);
}/*}}}*/
Beispiel #14
0
void zend_generator_close(zend_generator *generator, zend_bool finished_execution TSRMLS_DC) /* {{{ */
{
	if (generator->execute_data) {
		zend_execute_data *execute_data = generator->execute_data;
		zend_op_array *op_array = execute_data->op_array;

		if (!finished_execution) {
			if (op_array->has_finally_block) {
				/* -1 required because we want the last run opcode, not the
				 * next to-be-run one. */
				zend_uint op_num = execute_data->opline - op_array->opcodes - 1;
				zend_uint finally_op_num = 0;

				/* Find next finally block */
				int i;
				for (i = 0; i < op_array->last_try_catch; i++) {
					zend_try_catch_element *try_catch = &op_array->try_catch_array[i];

					if (op_num < try_catch->try_op) {
						break;
					}

					if (op_num < try_catch->finally_op) {
						finally_op_num = try_catch->finally_op;
					}
				}

				/* If a finally block was found we jump directly to it and
				 * resume the generator. Furthermore we abort this close call
				 * because the generator will already be closed somewhere in
				 * the resume. */
				if (finally_op_num) {
					execute_data->opline = &op_array->opcodes[finally_op_num];
					execute_data->leaving = ZEND_RETURN;
					generator->flags |= ZEND_GENERATOR_FORCED_CLOSE;
					zend_generator_resume(generator TSRMLS_CC);
					return;
				}
			}
		}

		if (!execute_data->symbol_table) {
			zend_free_compiled_variables(execute_data->CVs, op_array->last_var);
		} else {
			zend_clean_and_cache_symbol_table(execute_data->symbol_table TSRMLS_CC);
		}

		if (execute_data->current_this) {
			zval_ptr_dtor(&execute_data->current_this);
		}

		if (execute_data->object) {
			zval_ptr_dtor(&execute_data->object);
		}

		/* If the generator is closed before it can finish execution (reach
		 * a return statement) we have to free loop variables manually, as
		 * we don't know whether the SWITCH_FREE / FREE opcodes have run */
		if (!finished_execution) {
			/* -1 required because we want the last run opcode, not the
			 * next to-be-run one. */
			zend_uint 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 (brk_cont->start > op_num) {
					break;
				} else if (brk_cont->brk > op_num) {
					zend_op *brk_opline = op_array->opcodes + brk_cont->brk;

					switch (brk_opline->opcode) {
						case ZEND_SWITCH_FREE:
							{
								temp_variable *var = (temp_variable *) ((char *) execute_data->Ts + brk_opline->op1.var);
								zval_ptr_dtor(&var->var.ptr);
							}
							break;
						case ZEND_FREE:
							{
								temp_variable *var = (temp_variable *) ((char *) execute_data->Ts + brk_opline->op1.var);
								zval_dtor(&var->tmp_var);
							}
							break;
					}
				}
			}
		}

		/* Clear any backed up stack arguments */
		if (generator->backed_up_stack) {
			zval **zvals = (zval **) generator->backed_up_stack;
			size_t zval_num = generator->backed_up_stack_size / sizeof(zval *);
			int i;

			for (i = 0; i < zval_num; i++) {
				zval_ptr_dtor(&zvals[i]);
			}

			efree(generator->backed_up_stack);
		}

		if (generator->backed_up_arg_types_stack) {
			/* The arg types stack contains three elements per call: fbc, object
			 * and called_scope. Here we traverse the stack from top to bottom
			 * and dtor the object. */
			int i = generator->backed_up_arg_types_stack_count / 3;
			while (i--) {
				zval *object = (zval *) generator->backed_up_arg_types_stack[3*i + 1];
				if (object) {
					zval_ptr_dtor(&object);
				}
			}

			efree(generator->backed_up_arg_types_stack);
		} 

		/* We have added an additional stack frame in prev_execute_data, so we
		 * have to free it. It also contains the arguments passed to the
		 * generator (for func_get_args) so those have to be freed too. */
		{
			zend_execute_data *prev_execute_data = execute_data->prev_execute_data;
			void **arguments = prev_execute_data->function_state.arguments;

			if (arguments) {
				int arguments_count = (int) (zend_uintptr_t) *arguments;
				zval **arguments_start = (zval **) (arguments - arguments_count);
				int i;

				for (i = 0; i < arguments_count; ++i) {
					zval_ptr_dtor(arguments_start + i);
				}

				efree(arguments_start);
			}

			efree(prev_execute_data);
		}

		/* Free a clone of closure */
		if (op_array->fn_flags & ZEND_ACC_CLOSURE) {
			destroy_op_array(op_array TSRMLS_CC);
			efree(op_array);
		}

		efree(execute_data);
		generator->execute_data = NULL;
	}

	if (generator->value) {
		zval_ptr_dtor(&generator->value);
		generator->value = NULL;
	}

	if (generator->key) {
		zval_ptr_dtor(&generator->key);
		generator->key = NULL;
	}
}
Beispiel #15
0
PHP_SUHOSIN_API void suhosin_log(int loglevel, char *fmt, ...)
{
	int s, r, i=0, fd;
	long written, towrite;
	int getcaller=0;
	char *wbuf;
	struct timeval tv;
	time_t now;
	struct tm tm;
#if defined(AF_UNIX)
	struct sockaddr_un saun;
#endif
#ifdef PHP_WIN32
	LPTSTR strs[2];
	unsigned short etype;
	DWORD evid;
#endif
	char buf[5000];
	char error[5000];
	char *ip_address;
	char *fname;
	char *alertstring;
	int lineno;
	va_list ap;
	TSRMLS_FETCH();

#if PHP_VERSION_ID >= 50500
	getcaller = (loglevel & S_GETCALLER) == S_GETCALLER;
#endif
	/* remove the S_GETCALLER flag */
	loglevel = loglevel & ~S_GETCALLER;

	SDEBUG("(suhosin_log) loglevel: %d log_syslog: %u - log_sapi: %u - log_script: %u", loglevel, SUHOSIN_G(log_syslog), SUHOSIN_G(log_sapi), SUHOSIN_G(log_script));

	/* dump core if wanted */
	if (SUHOSIN_G(coredump) && loglevel == S_MEMORY) {
		volatile unsigned int *x = 0;
		volatile int y = *x;
	}
	
	if (SUHOSIN_G(log_use_x_forwarded_for)) {
		ip_address = suhosin_getenv("HTTP_X_FORWARDED_FOR", 20 TSRMLS_CC);
		if (ip_address == NULL) {
			ip_address = "X-FORWARDED-FOR not set";
		}
	} else {
		ip_address = suhosin_getenv("REMOTE_ADDR", 11 TSRMLS_CC);
		if (ip_address == NULL) {
			ip_address = "REMOTE_ADDR not set";
		}
	}
	
	
	va_start(ap, fmt);
	ap_php_vsnprintf(error, sizeof(error), fmt, ap);
	va_end(ap);
	while (error[i]) {
		if (error[i] < 32) error[i] = '.';
		i++;
	}
	
	if (SUHOSIN_G(simulation)) {
		alertstring = "ALERT-SIMULATION";
	} else {
		alertstring = "ALERT";
	}
	
	if (zend_is_executing(TSRMLS_C)) {
		zend_execute_data *exdata = EG(current_execute_data);
		if (exdata) {
			if (getcaller && exdata->prev_execute_data) {
				lineno = exdata->prev_execute_data->opline->lineno;
				fname = (char *)exdata->prev_execute_data->op_array->filename;									
			} else {
				lineno = exdata->opline->lineno;
				fname = (char *)exdata->op_array->filename;				
			}
		} else {
			lineno = zend_get_executed_lineno(TSRMLS_C);
			fname = (char *)zend_get_executed_filename(TSRMLS_C);
		}
		ap_php_snprintf(buf, sizeof(buf), "%s - %s (attacker '%s', file '%s', line %u)", alertstring, error, ip_address, fname, lineno);
	} else {
		fname = suhosin_getenv("SCRIPT_FILENAME", 15 TSRMLS_CC);
		if (fname==NULL) {
			fname = "unknown";
		}
		ap_php_snprintf(buf, sizeof(buf), "%s - %s (attacker '%s', file '%s')", alertstring, error, ip_address, fname);
	}
			
	/* Syslog-Logging disabled? */
	if (((SUHOSIN_G(log_syslog)|S_INTERNAL) & loglevel)==0) {
		goto log_file;
	}	
	
#if defined(AF_UNIX)
	ap_php_snprintf(error, sizeof(error), "<%u>suhosin[%u]: %s\n", (unsigned int)(SUHOSIN_G(log_syslog_facility)|SUHOSIN_G(log_syslog_priority)),getpid(),buf);

	s = socket(AF_UNIX, SOCK_DGRAM, 0);
	if (s == -1) {
		goto log_file;
	}
	
	memset(&saun, 0, sizeof(saun));
	saun.sun_family = AF_UNIX;
	strcpy(saun.sun_path, SYSLOG_PATH);
	/*saun.sun_len = sizeof(saun);*/
	
	r = connect(s, (struct sockaddr *)&saun, sizeof(saun));
	if (r) {
		close(s);
    		s = socket(AF_UNIX, SOCK_STREAM, 0);
		if (s == -1) {
			goto log_file;
		}
	
		memset(&saun, 0, sizeof(saun));
		saun.sun_family = AF_UNIX;
		strcpy(saun.sun_path, SYSLOG_PATH);
		/*saun.sun_len = sizeof(saun);*/

		r = connect(s, (struct sockaddr *)&saun, sizeof(saun));
		if (r) { 
			close(s);
			goto log_file;
		}
	}
	send(s, error, strlen(error), 0);
	
	close(s);
#endif
#ifdef PHP_WIN32
	ap_php_snprintf(error, sizeof(error), "suhosin[%u]: %s", getpid(),buf);

	switch (SUHOSIN_G(log_syslog_priority)) {			/* translate UNIX type into NT type */
		case 1: /*LOG_ALERT:*/
			etype = EVENTLOG_ERROR_TYPE;
			break;
		case 6: /*LOG_INFO:*/
			etype = EVENTLOG_INFORMATION_TYPE;
			break;
		default:
			etype = EVENTLOG_WARNING_TYPE;
	}
	evid = loglevel;
	strs[0] = error;
	/* report the event */
	if (log_source == NULL) {
		log_source = RegisterEventSource(NULL, "Suhosin-" SUHOSIN_EXT_VERSION);
	}
	ReportEvent(log_source, etype, (unsigned short) SUHOSIN_G(log_syslog_priority), evid, NULL, 1, 0, strs, NULL);
	
#endif
log_file:
	/* File-Logging disabled? */
	if ((SUHOSIN_G(log_file) & loglevel)==0) {
		goto log_sapi;
	}
	
	if (!SUHOSIN_G(log_filename) || !SUHOSIN_G(log_filename)[0]) {
		goto log_sapi;
	}
	fd = open(SUHOSIN_G(log_filename), O_CREAT|O_APPEND|O_WRONLY, 0640);
	if (fd == -1) {
	    suhosin_log(S_INTERNAL, "Unable to open logfile: %s", SUHOSIN_G(log_filename));
	    return;
	}

	gettimeofday(&tv, NULL);
	now = tv.tv_sec;
	php_gmtime_r(&now, &tm);
	ap_php_snprintf(error, sizeof(error), "%s %2d %02d:%02d:%02d [%u] %s\n", month_names[tm.tm_mon], tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, getpid(),buf);
	towrite = strlen(error);
	wbuf = error;
	php_flock(fd, LOCK_EX);
	while (towrite > 0) {
		written = write(fd, wbuf, towrite);
		if (written < 0) {
			break;
		}
		towrite -= written;
		wbuf += written;
	}
	php_flock(fd, LOCK_UN);
	close(fd);

log_sapi:
	/* SAPI Logging activated? */
	SDEBUG("(suhosin_log) log_syslog: %u - log_sapi: %u - log_script: %u - log_phpscript: %u", SUHOSIN_G(log_syslog), SUHOSIN_G(log_sapi), SUHOSIN_G(log_script), SUHOSIN_G(log_phpscript));
	if (((SUHOSIN_G(log_sapi)|S_INTERNAL) & loglevel)!=0) {
#if PHP_VERSION_ID < 50400
		sapi_module.log_message(buf);
#else
		sapi_module.log_message(buf TSRMLS_CC);
#endif
	}
	if ((SUHOSIN_G(log_stdout) & loglevel)!=0) {
		printf("%s\n", buf);
	}

/*log_script:*/
	/* script logging activaed? */
	if (((SUHOSIN_G(log_script) & loglevel)!=0) && SUHOSIN_G(log_scriptname)!=NULL) {
		char cmd[8192], *cmdpos, *bufpos;
		FILE *in;
		int space;
		struct stat st;
		
		char *sname = SUHOSIN_G(log_scriptname);
		while (isspace(*sname)) ++sname;
		if (*sname == 0) goto log_phpscript;
		
		if (VCWD_STAT(sname, &st) < 0) {
			suhosin_log(S_INTERNAL, "unable to find logging shell script %s - file dropped", sname);
			goto log_phpscript;
		}
		if (access(sname, X_OK|R_OK) < 0) {
			suhosin_log(S_INTERNAL, "logging shell script %s is not executable - file dropped", sname);
			goto log_phpscript;					
		}
		
		/* TODO: clean up this code to calculate size of output dynamically */
		ap_php_snprintf(cmd, sizeof(cmd) - 20, "%s %s \'", sname, loglevel2string(loglevel));
		space = sizeof(cmd) - strlen(cmd) - 20;
		cmdpos = cmd + strlen(cmd);
		bufpos = buf;
		if (space <= 1) return;
		while (space > 2 && *bufpos) {
			if (*bufpos == '\'') {
				if (space<=5) break;
				*cmdpos++ = '\'';
				*cmdpos++ = '\\';
				*cmdpos++ = '\'';
				*cmdpos++ = '\'';
				bufpos++;
				space-=4;
			} else {
				*cmdpos++ = *bufpos++;
				space--;
			}
		}
		*cmdpos++ = '\'';
		*cmdpos++ = ' ';
		*cmdpos++ = '2';
		*cmdpos++ = '>';
		*cmdpos++ = '&';
		*cmdpos++ = '1';
		*cmdpos = 0;
		
		if ((in=VCWD_POPEN(cmd, "r"))==NULL) {
			suhosin_log(S_INTERNAL, "Unable to execute logging shell script: %s", sname);
			goto log_phpscript;
		}
		/* read and forget the result */
		while (1) {
			int readbytes = fread(cmd, 1, sizeof(cmd), in);
			if (readbytes<=0) {
				break;
			}
			if (strncmp(cmd, "sh: ", 4) == 0) {
				/* assume this is an error */
				suhosin_log(S_INTERNAL, "Error while executing logging shell script: %s", sname);
				pclose(in);
				goto log_phpscript;
			}
		}
		pclose(in);
	}
log_phpscript:
	if ((SUHOSIN_G(log_phpscript) & loglevel)!=0 && EG(in_execution) && SUHOSIN_G(log_phpscriptname) && SUHOSIN_G(log_phpscriptname)[0]) {
		zend_file_handle file_handle;
		zend_op_array *new_op_array;
		zval *result = NULL;
		
		long orig_execution_depth = SUHOSIN_G(execution_depth);
#if PHP_VERSION_ID < 50400
		zend_bool orig_safe_mode = PG(safe_mode);
#endif
		char *orig_basedir = PG(open_basedir);
		
		char *phpscript = SUHOSIN_G(log_phpscriptname);
SDEBUG("scriptname %s", SUHOSIN_G(log_phpscriptname));				
#ifdef ZEND_ENGINE_2
		if (zend_stream_open(phpscript, &file_handle TSRMLS_CC) == SUCCESS) {
#else
		if (zend_open(phpscript, &file_handle) == SUCCESS && ZEND_IS_VALID_FILE_HANDLE(&file_handle)) {
			file_handle.filename = phpscript;
			file_handle.free_filename = 0;
#endif		
			if (!file_handle.opened_path) {
				file_handle.opened_path = estrndup(phpscript, strlen(phpscript));
			}
			new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE TSRMLS_CC);
			zend_destroy_file_handle(&file_handle TSRMLS_CC);
			if (new_op_array) {
				HashTable *active_symbol_table = EG(active_symbol_table);
				zval *zerror, *zerror_class;
				
				if (active_symbol_table == NULL) {
					active_symbol_table = &EG(symbol_table);
				}
				EG(return_value_ptr_ptr) = &result;
				EG(active_op_array) = new_op_array;
				
				MAKE_STD_ZVAL(zerror);
				MAKE_STD_ZVAL(zerror_class);
				ZVAL_STRING(zerror, buf, 1);
				ZVAL_LONG(zerror_class, loglevel);

				zend_hash_update(active_symbol_table, "SUHOSIN_ERROR", sizeof("SUHOSIN_ERROR"), (void **)&zerror, sizeof(zval *), NULL);
				zend_hash_update(active_symbol_table, "SUHOSIN_ERRORCLASS", sizeof("SUHOSIN_ERRORCLASS"), (void **)&zerror_class, sizeof(zval *), NULL);
				
				SUHOSIN_G(execution_depth) = 0;
				if (SUHOSIN_G(log_phpscript_is_safe)) {
#if PHP_VERSION_ID < 50400
					PG(safe_mode) = 0;
#endif
					PG(open_basedir) = NULL;
				}
				
				zend_execute(new_op_array TSRMLS_CC);
				
				SUHOSIN_G(execution_depth) = orig_execution_depth;
#if PHP_VERSION_ID < 50400				
				PG(safe_mode) = orig_safe_mode;
#endif
				PG(open_basedir) = orig_basedir;
				
#ifdef ZEND_ENGINE_2
				destroy_op_array(new_op_array TSRMLS_CC);
#else
				destroy_op_array(new_op_array);
#endif
				efree(new_op_array);
#ifdef ZEND_ENGINE_2
				if (!EG(exception))
#endif			
				{
					if (EG(return_value_ptr_ptr)) {
						zval_ptr_dtor(EG(return_value_ptr_ptr));
						EG(return_value_ptr_ptr) = NULL;
					}
				}
			} else {
				suhosin_log(S_INTERNAL, "Unable to execute logging PHP script: %s", SUHOSIN_G(log_phpscriptname));
				return;
			}
		} else {
			suhosin_log(S_INTERNAL, "Unable to execute logging PHP script: %s", SUHOSIN_G(log_phpscriptname));
			return;
		}
	}

}
/* {{{ php_runkit_sandbox_parent_include_or_eval
	What's the point of running in a sandbox if you can leave whenever you want to???
 */
static void php_runkit_sandbox_parent_include_or_eval(INTERNAL_FUNCTION_PARAMETERS, int type, int once)
{
	php_runkit_sandbox_parent_object *objval;
	zval *zcode;
	int bailed_out = 0;
	zval *retval = NULL;

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &zcode) == FAILURE) {
		RETURN_FALSE;
	}

	convert_to_string(zcode);

	PHP_RUNKIT_SANDBOX_PARENT_FETCHBOX_VERIFY_ACCESS(objval, this_ptr);
	if (type == ZEND_EVAL && !objval->self->parent_eval) {
		php_error_docref(NULL, E_WARNING, "Access to eval() code in the parent context is not enabled");
		RETURN_FALSE;
	}
	if (type != ZEND_EVAL && !objval->self->parent_include) {
		php_error_docref(NULL, E_WARNING, "Access to include()/include_once()/require()/require_once() in the parent context is not enabled");
		RETURN_FALSE;
	}

	RETVAL_NULL();

	PHP_RUNKIT_SANDBOX_PARENT_BEGIN(objval)
		zend_op_array *op_array = NULL;
		int already_included = 0;

		op_array = php_runkit_sandbox_include_or_eval_int(return_value, zcode, type, once, &already_included);

		if (op_array) {
			HashTable *old_symbol_table = EG(active_symbol_table);
			zval **orig_retvalpp = EG(return_value_ptr_ptr);
			zend_op_array *orig_act_oparray = EG(active_op_array);

			EG(return_value_ptr_ptr) = &retval;
			EG(active_op_array) = op_array;
			EG(active_symbol_table) = php_runkit_sandbox_parent_resolve_symbol_table(objval);

			zend_execute(op_array);

			if (retval) {
				*return_value = *retval;
			} else {
				RETVAL_TRUE;
			}

			destroy_op_array(op_array);
			efree(op_array);

			EG(return_value_ptr_ptr) = orig_retvalpp;
			EG(active_op_array) = orig_act_oparray;
			EG(active_symbol_table) = old_symbol_table;
		} else if ((type != ZEND_INCLUDE) && !already_included) {
			/* include can fail to parse peacefully,
			 * require and eval should die on failure
			 */
			bailed_out = 1;
		}
	PHP_RUNKIT_SANDBOX_PARENT_END(objval)

	if (bailed_out) {
		CG(unclean_shutdown) = 1;
		CG(in_compilation) = EG(in_execution) = 0;
		EG(current_execute_data) = NULL;
		PHP_RUNKIT_SANDBOX_PARENT_BEGIN(objval)
			zend_bailout();
		PHP_RUNKIT_SANDBOX_PARENT_END(objval)
	}

	PHP_SANDBOX_CROSS_SCOPE_ZVAL_COPY_CTOR(return_value);

	/* Don't confuse the memory manager */
	if (retval) {
		PHP_RUNKIT_SANDBOX_PARENT_BEGIN(objval)
		zval_ptr_dtor(&retval);
		PHP_RUNKIT_SANDBOX_PARENT_END(objval)
	}
}
Beispiel #17
0
ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished_execution TSRMLS_DC) /* {{{ */
{
	if (generator->execute_data) {
		zend_execute_data *execute_data = generator->execute_data;
		zend_op_array *op_array = execute_data->op_array;

		if (!finished_execution) {
			if (op_array->has_finally_block) {
				/* -1 required because we want the last run opcode, not the
  				 * next to-be-run one. */
				zend_uint op_num = execute_data->opline - op_array->opcodes - 1;
				zend_uint finally_op_num = 0;

				/* Find next finally block */
				int i;
				for (i = 0; i < op_array->last_try_catch; i++) {
					zend_try_catch_element *try_catch = &op_array->try_catch_array[i];

					if (op_num < try_catch->try_op) {
						break;
					}

					if (op_num < try_catch->finally_op) {
						finally_op_num = try_catch->finally_op;
					}
				}

				/* If a finally block was found we jump directly to it and
				 * resume the generator. Furthermore we abort this close call
				 * because the generator will already be closed somewhere in
				 * the resume. */
				if (finally_op_num) {
					execute_data->opline = &op_array->opcodes[finally_op_num];
					execute_data->fast_ret = NULL;
					generator->flags |= ZEND_GENERATOR_FORCED_CLOSE;
					zend_generator_resume(generator TSRMLS_CC);
					return;
				}
			}
		}

		if (!execute_data->symbol_table) {
			zend_free_compiled_variables(execute_data);
		} else {
			zend_clean_and_cache_symbol_table(execute_data->symbol_table TSRMLS_CC);
		}

		if (execute_data->current_this) {
			zval_ptr_dtor(&execute_data->current_this);
		}

		/* If the generator is closed before it can finish execution (reach
		 * a return statement) we have to free loop variables manually, as
		 * we don't know whether the SWITCH_FREE / FREE opcodes have run */
		if (!finished_execution) {
			/* -1 required because we want the last run opcode, not the
			 * next to-be-run one. */
			zend_uint 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 (brk_cont->start > op_num) {
					break;
				} else if (brk_cont->brk > op_num) {
					zend_op *brk_opline = op_array->opcodes + brk_cont->brk;

					switch (brk_opline->opcode) {
						case ZEND_SWITCH_FREE:
							{
								temp_variable *var = EX_TMP_VAR(execute_data, brk_opline->op1.var);
								zval_ptr_dtor(&var->var.ptr);
							}
							break;
						case ZEND_FREE:
							{
								temp_variable *var = EX_TMP_VAR(execute_data, brk_opline->op1.var);
								zval_dtor(&var->tmp_var);
							}
							break;
					}
				}
			}
		}

		/* Clear any backed up stack arguments */
		if (generator->stack != EG(argument_stack)) {
			void **stack_frame = zend_vm_stack_frame_base(execute_data);
			while (generator->stack->top != stack_frame) {
				zval_ptr_dtor((zval**)stack_frame);
				stack_frame++;
			}
		}

		while (execute_data->call >= execute_data->call_slots) {
			if (execute_data->call->object) {
				zval_ptr_dtor(&execute_data->call->object);
			}
			execute_data->call--;
		}

		/* We have added an additional stack frame in prev_execute_data, so we
		 * have to free it. It also contains the arguments passed to the
		 * generator (for func_get_args) so those have to be freed too. */
		{
			zend_execute_data *prev_execute_data = execute_data->prev_execute_data;
			void **arguments = prev_execute_data->function_state.arguments;

			if (arguments) {
				int arguments_count = (int) (zend_uintptr_t) *arguments;
				zval **arguments_start = (zval **) (arguments - arguments_count);
				int i;

				for (i = 0; i < arguments_count; ++i) {
					zval_ptr_dtor(arguments_start + i);
				}
			}
		}

		/* Free a clone of closure */
		if (op_array->fn_flags & ZEND_ACC_CLOSURE) {
			destroy_op_array(op_array TSRMLS_CC);
			efree(op_array);
		}

		efree(generator->stack);
		if (generator->stack == EG(argument_stack)) {
			/* abnormal exit for running generator */
			EG(argument_stack) = NULL;
		}
		generator->execute_data = NULL;
	}

	if (generator->value) {
		zval_ptr_dtor(&generator->value);
		generator->value = NULL;
	}

	if (generator->key) {
		zval_ptr_dtor(&generator->key);
		generator->key = NULL;
	}
}
Beispiel #18
0
/**
 * Do an internal require to a plain php file taking care of the value returned by the file
 */
int zephir_require_ret(zval *return_value_ptr, const char *require_path)
{
	zend_file_handle file_handle;
	int ret;
	zend_op_array *new_op_array;
	zval dummy, local_retval;

	ZVAL_UNDEF(&local_retval);

#ifndef ZEPHIR_RELEASE
	if (return_value_ptr != NULL && Z_TYPE_P(return_value_ptr) > IS_NULL) {
		fprintf(stderr, "%s: *return_value_ptr is expected to be NULL", __func__);
		zephir_print_backtrace();
		abort();
	}
#endif

	/* if (!memcmp(require_path, "", 0)) {
		@TODO, throw an exception here
		return FAILURE;
	} */

	file_handle.filename = require_path;
	file_handle.free_filename = 0;
	file_handle.type = ZEND_HANDLE_FILENAME;
	file_handle.opened_path = NULL;
	file_handle.handle.fp = NULL;

	new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE);
	if (new_op_array) {

		if (file_handle.handle.stream.handle) {
			ZVAL_NULL(&dummy);
			if (!file_handle.opened_path) {
				file_handle.opened_path = zend_string_init(require_path, strlen(require_path), 0);
			}

			zend_hash_add(&EG(included_files), file_handle.opened_path, &dummy);
			zend_destroy_file_handle(&file_handle);
		}

		new_op_array->scope = EG(scope);
		zend_execute(new_op_array, &local_retval);

		if (return_value_ptr) {
			zval_ptr_dtor(return_value_ptr);
			ZVAL_COPY_VALUE(return_value_ptr, &local_retval);
		} else {
			zval_ptr_dtor(&local_retval);
		}

		destroy_op_array(new_op_array);
		efree_size(new_op_array, sizeof(zend_op_array));

		if (EG(exception)) {
			ret = FAILURE;
		} else {
			ret = SUCCESS;
		}

		return ret;
	} else {
		zend_destroy_file_handle(&file_handle);
	}

	return FAILURE;
}