예제 #1
0
/**
 * This is a function to call PHP functions in a old-style secure way
 */
static inline int phalcon_call_func_normal(zval *return_value, char *func_name, int func_length, int noreturn TSRMLS_DC){

	zval *fn = NULL;
	int status = FAILURE;

	if (!noreturn) {
		ALLOC_INIT_ZVAL(return_value);
	}

	PHALCON_ALLOC_ZVAL(fn);
	ZVAL_STRINGL(fn, func_name, func_length, 0);

	status = phalcon_call_user_function(CG(function_table), NULL, fn, return_value, 0, NULL TSRMLS_CC);
	if (status == FAILURE) {
		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Call to undefined function %s()", func_name);
	}

	ZVAL_NULL(fn);
	zval_ptr_dtor(&fn);

	if (!noreturn) {
		zval_ptr_dtor(&return_value);
	}

	if (EG(exception)) {
		status = FAILURE;
	}

	if (status == FAILURE) {
		phalcon_memory_restore_stack(TSRMLS_C);
	}

	return status;
}
예제 #2
0
void test_phalcon_alloc_zval(void)
{
	startup_php(__func__);
	zend_first_try {
		zval* x;

		PHALCON_MM_GROW();
			PHALCON_ALLOC_ZVAL(x);

			CU_ASSERT_EQUAL(Z_REFCOUNT_P(x), 1);
			CU_ASSERT_EQUAL(Z_ISREF_P(x), 0);
			CU_ASSERT_EQUAL(Z_TYPE_P(x), IS_NULL);
		PHALCON_MM_RESTORE();

		/* zvals allocated by PHALCON_ALLOC_ZVAL() should not be affected by PHALCON_MM_RESTORE() */
		CU_ASSERT_EQUAL(_mem_block_check(x, 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC), 1);
		CU_ASSERT_EQUAL(Z_REFCOUNT_P(x), 1);

		zval_ptr_dtor(&x);
	}
	zend_catch {
		CU_ASSERT(0);
	}
	zend_end_try();

	shutdown_php();
	CU_ASSERT_EQUAL(leaks, 0);
}
예제 #3
0
/**
 * This function implements a secure old-style way to call functions
 */
static inline int phalcon_call_method_normal(zval *return_value, zval *object, char *method_name, int method_len, int check, int noreturn TSRMLS_DC){

	zval *fn = NULL;
	int status = FAILURE;
	zend_class_entry *ce, *active_scope = NULL;

	if (Z_TYPE_P(object) != IS_OBJECT) {
		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Call to method %s() on a non object", method_name);
		phalcon_memory_restore_stack(TSRMLS_C);
		return FAILURE;
	}

	ce = Z_OBJCE_P(object);

	if (check) {
		if (!zend_hash_exists(&ce->function_table, method_name, method_len+1)) {
			return SUCCESS;
		}
	}

	if (!noreturn) {
		ALLOC_INIT_ZVAL(return_value);
	}

	PHALCON_ALLOC_ZVAL(fn);
	ZVAL_STRINGL(fn, method_name, method_len, 0);

	active_scope = EG(scope);

	/* Find class_entry scope */
	if (ce->parent) {
		phalcon_find_scope(ce, method_name, method_len TSRMLS_CC);
	} else {
		EG(scope) = ce;
	}

	status = phalcon_call_user_function(&ce->function_table, &object, fn, return_value, 0, NULL TSRMLS_CC);
	if (status == FAILURE) {
		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Call to undefined method %s()", method_name);
	}
	EG(scope) = active_scope;

	ZVAL_NULL(fn);
	zval_ptr_dtor(&fn);

	if (!noreturn) {
		zval_ptr_dtor(&return_value);
	}

	if (EG(exception)) {
		status = FAILURE;
	}

	if (status == FAILURE) {
		phalcon_memory_restore_stack(TSRMLS_C);
	}

	return status;
}
예제 #4
0
파일: fcall.c 프로젝트: gplanchat/cphalcon
/**
 * Call methods that require parameters in a old-style secure way
 */
inline int phalcon_call_method_params_normal(zval *return_value, zval *object, char *method_name, int method_len, zend_uint param_count, zval *params[], int check, int noreturn TSRMLS_DC){

	zval *fn = NULL;
	int status = FAILURE;
	zend_class_entry *ce, *active_scope = NULL;

	if (check) {
		if (!zend_hash_exists(&Z_OBJCE_P(object)->function_table, method_name, method_len+1)) {
			return SUCCESS;
		}
	}

	if (!noreturn) {
		ALLOC_INIT_ZVAL(return_value);
	}

	PHALCON_ALLOC_ZVAL(fn);
	ZVAL_STRINGL(fn, method_name, method_len, 1);

	if (Z_TYPE_P(object) == IS_OBJECT) {
		active_scope = EG(scope);
		ce = Z_OBJCE_P(object);
		phalcon_find_scope(ce, method_name, method_len TSRMLS_CC);
		status = PHALCON_CALL_USER_FUNCTION(&ce->function_table, &object, fn, return_value, param_count, params TSRMLS_CC);
		if (status == FAILURE) {
			EG(scope) = active_scope;
			php_error_docref(NULL TSRMLS_CC, E_ERROR, "Call to undefined method %s() on class %s", Z_STRVAL_P(fn), Z_OBJCE_P(object)->name);
			status = FAILURE;
		}
		EG(scope) = active_scope;
	} else {
		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Call to method %s() on a non object", Z_STRVAL_P(fn));
		status = FAILURE;
	}

	zval_ptr_dtor(&fn);

	if (!noreturn) {
		zval_ptr_dtor(&return_value);
		return_value = NULL;
	}

	if (EG(exception)){
		status = FAILURE;
	}

	if (status == FAILURE) {
		phalcon_memory_restore_stack(TSRMLS_C);
	}

	return status;
}
예제 #5
0
파일: fcall.c 프로젝트: xingskycn/cphalcon
/**
 * Call single function which requires arbitrary number of parameters
 */
int phalcon_call_func_params(zval *return_value, char *func_name, int func_length, zend_uint param_count, zval *params[], int noreturn, int fcache_pointer TSRMLS_DC){

	zval *fn = NULL;
	int status = FAILURE;
	//zval ***params_array;
	zval *local_retval_ptr = NULL;
	//int i;

	if (!noreturn) {
		ALLOC_INIT_ZVAL(return_value);
	}

	PHALCON_ALLOC_ZVAL(fn);
	ZVAL_STRINGL(fn, func_name, func_length, 1);

	/*status = phalcon_cache_lookup_function(fn, fcache_pointer);
	if (status == FAILURE) {
		return FAILURE;
	}*/

	/*if(param_count){
		params_array = (zval ***) emalloc(sizeof(zval **)*param_count);
		for (i=0; i<param_count; i++) {
			params_array[i] = &params[i];
		}
	} else {
		params_array = NULL;
	}*/

	status = call_user_function(CG(function_table), NULL, fn, return_value, param_count, params TSRMLS_CC);
	//status = phalcon_call_user_function_ex(CG(function_table), NULL, fn, &local_retval_ptr, param_count, params_array, 1, NULL, phalcon_fcall_cache[fcache_pointer] TSRMLS_CC);
	if (status == FAILURE) {
		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Call to undefined function %s()", func_name);
		return FAILURE;
	}

	zval_ptr_dtor(&fn);

	if (local_retval_ptr) {
		COPY_PZVAL_TO_ZVAL(*return_value, local_retval_ptr);
	}

	if (!noreturn) {
		zval_ptr_dtor(&return_value);
	}

	/*if (params_array) {
		efree(params_array);
	}*/

	return status;
}
예제 #6
0
파일: fcall.c 프로젝트: xingskycn/cphalcon
/**
 * Call method on an object which not requires parameters
 *
 */
int phalcon_call_method(zval *return_value, zval *object, char *method_name, int method_len, int check, int noreturn TSRMLS_DC){

	zval *fn = NULL;
	int status = FAILURE;
	zend_class_entry *active_scope = NULL;

	if (check) {
		if (!zend_hash_exists(&Z_OBJCE_P(object)->function_table, method_name, strlen(method_name)+1)) {
			return FAILURE;
		}
	}

	if(!noreturn){
		ALLOC_INIT_ZVAL(return_value);
	}

	PHALCON_ALLOC_ZVAL(fn);
	ZVAL_STRINGL(fn, method_name, method_len, 1);

	if (Z_TYPE_P(object) == IS_OBJECT) {
		active_scope = EG(scope);
		phalcon_find_scope(Z_OBJCE_P(object), method_name, method_len TSRMLS_CC);
		status = call_user_function(&Z_OBJCE_P(object)->function_table, &object, fn, return_value, 0, NULL TSRMLS_CC);
		if (status == FAILURE) {
			php_error_docref(NULL TSRMLS_CC, E_ERROR, "Call to undefined method %s()", Z_STRVAL_P(fn));
			return FAILURE;
		}
		EG(scope) = active_scope;
	} else {
		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Call to method %s() on a non object", Z_STRVAL_P(fn));
		return FAILURE;
	}

	zval_ptr_dtor(&fn);

	if (!noreturn) {
		zval_ptr_dtor(&return_value);
	}

	return status;
}
예제 #7
0
파일: fcall.c 프로젝트: gplanchat/cphalcon
/**
 * This is a function to call PHP functions in a old-style secure way
 */
inline int phalcon_call_func_normal(zval *return_value, char *func_name, int func_length, int noreturn TSRMLS_DC){

	zval *fn = NULL;
	int status = FAILURE;
	zval *local_retval_ptr = NULL;

	if (!noreturn) {
		ALLOC_INIT_ZVAL(return_value);
	}

	PHALCON_ALLOC_ZVAL(fn);
	ZVAL_STRINGL(fn, func_name, func_length, 1);

	status = PHALCON_CALL_USER_FUNCTION(CG(function_table), NULL, fn, return_value, 0, NULL TSRMLS_CC);
	if (status == FAILURE) {
		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Call to undefined function %s()", func_name);
	}

	zval_ptr_dtor(&fn);

	if (local_retval_ptr) {
		COPY_PZVAL_TO_ZVAL(*return_value, local_retval_ptr);
	}

	if (!noreturn) {
		zval_ptr_dtor(&return_value);
	}

	if (EG(exception)){
		status = FAILURE;
	}

	if (status == FAILURE) {
		phalcon_memory_restore_stack(TSRMLS_C);
	}

	return status;
}
예제 #8
0
파일: fcall.c 프로젝트: xingskycn/cphalcon
/**
 * Call single function which not requires parameters
 */
int phalcon_call_func(zval *return_value, char *func_name, int func_length, int noreturn, int fcache_pointer TSRMLS_DC){

	zval *fn = NULL;
	int status = FAILURE;
	zval *local_retval_ptr = NULL;

	if (!noreturn) {
		ALLOC_INIT_ZVAL(return_value);
	}

	PHALCON_ALLOC_ZVAL(fn);
	ZVAL_STRINGL(fn, func_name, func_length, 1);

	/*status = phalcon_cache_lookup_function(fn, fcache_pointer);
	if (status == FAILURE) {
		return FAILURE;
	}*/

	status = call_user_function(CG(function_table), NULL, fn, return_value, 0, NULL TSRMLS_CC);
	//status = phalcon_call_user_function_ex(CG(function_table), NULL, fn, &local_retval_ptr, 0, NULL, 1, NULL, phalcon_fcall_cache[fcache_pointer] TSRMLS_CC);
	if (status == FAILURE) {
		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Call to undefined function %s()", func_name);
		return FAILURE;
	}

	zval_ptr_dtor(&fn);

	if (local_retval_ptr) {
		COPY_PZVAL_TO_ZVAL(*return_value, local_retval_ptr);
	}

	if (!noreturn) {
		zval_ptr_dtor(&return_value);
	}

	return status;
}
예제 #9
0
/**
 * Applies a format to a message before sending it to the log
 *
 * @param string $message
 * @param int $type
 * @param int $timestamp
 * @return string
 */
PHP_METHOD(Phalcon_Logger_Formatter_Firephp, format) {

	zval *message, *type, *type_str = NULL, *timestamp;
	zval *payload, *body, *backtrace, *meta, *encoded;
	zval *show_backtrace;
	smart_str result = { NULL, 0, 0 };
	int i;
	Bucket *p;

	phalcon_fetch_params(0, 3, 0, &message, &type, &timestamp);

	/**
	 * We intentionally do not use Phalcon's MM for better performance.
	 * All variables allocated with PHALCON_ALLOC_ZVAL() will have
	 * their reference count set to 1 and therefore they can be nicely
	 * put into the result array; when that array will be destroyed,
	 * all inserted variables will be automatically destroyed, too
	 * and we will just save some time by not using Z_ADDREF_P and Z_DELREF_P
	 */

	PHALCON_ALLOC_ZVAL(type_str);
	phalcon_call_method_p1(type_str, this_ptr, "gettypestring", type);

	phalcon_read_property_this(&show_backtrace, getThis(), SL("_showBacktrace"), PH_NOISY TSRMLS_CC);
	Z_DELREF_P(show_backtrace);

	/**
	 * Get the backtrace. This differs for differemt PHP versions.
	 * 5.3.6+ allows us to skip the function arguments which will save some memory
	 * For 5.4+ there is an extra argument.
	 */
	PHALCON_ALLOC_ZVAL(backtrace);
	if (zend_is_true(show_backtrace)) {
#if PHP_VERSION_ID < 50306
		zend_fetch_debug_backtrace(backtrace, 1, 0 TSRMLS_CC);
#elif PHP_VERSION_ID < 50400
		zend_fetch_debug_backtrace(backtrace, 1, DEBUG_BACKTRACE_IGNORE_ARGS TSRMLS_CC);
#else
		zend_fetch_debug_backtrace(backtrace, 1, DEBUG_BACKTRACE_IGNORE_ARGS, 0 TSRMLS_CC);
#endif

		if (Z_TYPE_P(backtrace) == IS_ARRAY) {
			HashPosition pos;
			HashTable *ht = Z_ARRVAL_P(backtrace);
			zval **ppzval;
			int found = 0;
			ulong idx;
			char *key;
			uint key_len;

			/**
			 * At this point we know that the backtrace is the array.
			 * Again, we intentionally do not use Phalcon's API because we know
			 * that we are working with the array / hash table and thus we can
			 * save some time by omitting Z_TYPE_P(x) == IS_ARRAY checks
			 */

			for (
				zend_hash_internal_pointer_reset_ex(ht, &pos);
				zend_hash_has_more_elements_ex(ht, &pos) == SUCCESS;
			) {
				zend_hash_get_current_data_ex(ht, (void**)&ppzval, &pos);
				zend_hash_get_current_key_ex(ht, &key, &key_len, &idx, 0, &pos);
				zend_hash_move_forward_ex(ht, &pos);

				if (Z_TYPE_PP(ppzval) == IS_ARRAY) {
					/**
					 * Here we need to skip the latest calls into Phalcon's core.
					 * Calls to Zend internal functions will have "file" index not set.
					 * We remove these entries from the array.
					 */
					if (!found && !zend_hash_exists(Z_ARRVAL_PP(ppzval), SS("file"))) {
						zend_hash_index_del(ht, idx);
					}
					else {
						/**
						 * Remove args and object indices. They usually give
						 * too much information; this is not suitable to send
						 * in the HTTP headers
						 */
						zend_hash_del(Z_ARRVAL_PP(ppzval), "args", sizeof("args"));
						zend_hash_del(Z_ARRVAL_PP(ppzval), "object", sizeof("object"));
						found = 1;
					}
				}
			}

			/**
			 * Now we need to renumber the hash table because we removed several
			 * heading elements. If we don't do this, json_encode() will convert
			 * this array to a JavaScript object which is an unwanted side effect
			 */
			p = ht->pListHead;
			i = 0;
			while (p != NULL) {
				p->nKeyLength = 0;
				p->h = i++;
				p = p->pListNext;
			}

			ht->nNextFreeElement = i;
			zend_hash_rehash(ht);
		}
	}

	/**
	 * The result will looks like this:
	 *
	 * array(
	 *     array('Type' => 'message type', 'Label' => 'message'),
	 *     array('backtrace' => array(backtrace goes here)
	 * )
	 */
	MAKE_STD_ZVAL(payload);
	array_init_size(payload, 2);

	PHALCON_ALLOC_ZVAL(meta);
	array_init_size(meta, 4);
	add_assoc_zval_ex(meta, SS("Type"), type_str);
	Z_ADDREF_P(message);
	add_assoc_zval_ex(meta, SS("Label"), message);

	if (Z_TYPE_P(backtrace) == IS_ARRAY) {
		zval **ppzval;

		if (likely(SUCCESS == zend_hash_index_find(Z_ARRVAL_P(backtrace), 0, (void**)&ppzval)) && likely(Z_TYPE_PP(ppzval) == IS_ARRAY)) {
			zval **file = NULL, **line = NULL;

			zend_hash_quick_find(Z_ARRVAL_PP(ppzval), SS("file"), zend_inline_hash_func(SS("file")), (void**)&file);
			zend_hash_quick_find(Z_ARRVAL_PP(ppzval), SS("line"), zend_inline_hash_func(SS("line")), (void**)&line);

			if (likely(file != NULL)) {
				Z_ADDREF_PP(file);
				add_assoc_zval_ex(meta, SS("File"), *file);
			}

			if (likely(line != NULL)) {
				Z_ADDREF_PP(line);
				add_assoc_zval_ex(meta, SS("Line"), *line);
			}
		}
	}

	MAKE_STD_ZVAL(body);
	array_init_size(body, 1);

	if (zend_is_true(show_backtrace)) {
		add_assoc_zval_ex(body, SS("backtrace"), backtrace);
	}
	else {
		zval_ptr_dtor(&backtrace);
	}

	add_next_index_zval(payload, meta);
	add_next_index_zval(payload, body);

	/**
	 * Convert everything to JSON
	 */
	ALLOC_INIT_ZVAL(encoded);
	phalcon_json_encode(encoded, payload, 0 TSRMLS_CC);

	/**
	 * As promised, kill the payload and all associated elements
	 */
	zval_ptr_dtor(&payload);

	/**
	 * We don't want to use Phalcon's concatenation API because it
	 * requires the memory manager. Therefore we fall back to using smart strings.
	 * smart_str_alloc4() will allocate all required memory amount (plus some more)
	 * in one go and this allows us to avoid performance penalties due to
	 * memory reallocations.
	 */
	smart_str_alloc4(&result, Z_STRLEN_P(encoded) + 2 + 5, 0, i);

	/**
	 * The format is:
	 *
	 * <size>|[meta,body]|
	 *
	 * Meta and body are contained in encoded inside the array, as required
	 * by the protocol specification
	 * @see http://www.firephp.org/Wiki/Reference/Protocol
	 */
	smart_str_append_long(&result, Z_STRLEN_P(encoded));
	smart_str_appendc(&result, '|');
	smart_str_appendl(&result, Z_STRVAL_P(encoded), Z_STRLEN_P(encoded));
	smart_str_appendc(&result, '|');
	smart_str_0(&result);

	/* We don't need the JSON message anymore */
	zval_ptr_dtor(&encoded);
	/* Do not free the samrt string because we steal its data for zval */
	RETURN_STRINGL(result.c, result.len, 0);
}