Beispiel #1
0
/* php_spintf_appendstring() {{{ */
inline static void
php_sprintf_appendstring(char **buffer, int *pos, int *size, char *add,
						   int min_width, int max_width, char padding,
						   int alignment, int len, int neg, int expprec, int always_sign)
{
	register int npad;
	int req_size;
	int copy_len;
	int m_width;

	copy_len = (expprec ? MIN(max_width, len) : len);
	npad = min_width - copy_len;

	if (npad < 0) {
		npad = 0;
	}
	
	PRINTF_DEBUG(("sprintf: appendstring(%x, %d, %d, \"%s\", %d, '%c', %d)\n",
				  *buffer, *pos, *size, add, min_width, padding, alignment));
	m_width = MAX(min_width, copy_len);

	if(m_width > INT_MAX - *pos - 1) {
		zend_error_noreturn(E_ERROR, "Field width %d is too long", m_width);
	}

	req_size = *pos + m_width + 1;

	if (req_size > *size) {
		while (req_size > *size) {
			if(*size > INT_MAX/2) {
				zend_error_noreturn(E_ERROR, "Field width %d is too long", req_size); 
			}
			*size <<= 1;
		}
		PRINTF_DEBUG(("sprintf ereallocing buffer to %d bytes\n", *size));
		*buffer = erealloc(*buffer, *size);
	}
	if (alignment == ALIGN_RIGHT) {
		if ((neg || always_sign) && padding=='0') {
			(*buffer)[(*pos)++] = (neg) ? '-' : '+';
			add++;
			len--;
			copy_len--;
		}
		while (npad-- > 0) {
			(*buffer)[(*pos)++] = padding;
		}
	}
	PRINTF_DEBUG(("sprintf: appending \"%s\"\n", add));
	memcpy(&(*buffer)[*pos], add, copy_len + 1);
	*pos += copy_len;
	if (alignment == ALIGN_LEFT) {
		while (npad--) {
			(*buffer)[(*pos)++] = padding;
		}
	}
}
Beispiel #2
0
/* {{{ zend_signal_register
 *  Set a handler for a signal we want to defer.
 *  Previously set handler must have been saved before.
 */
static int zend_signal_register(int signo, void (*handler)(int, siginfo_t*, void*))
{
	struct sigaction sa = {{0}};

	if (sigaction(signo, NULL, &sa) == 0) {
		if ((sa.sa_flags & SA_SIGINFO) && sa.sa_sigaction == handler) {
			return FAILURE;
		}

		SIGG(handlers)[signo-1].flags = sa.sa_flags;
		if (sa.sa_flags & SA_SIGINFO) {
			SIGG(handlers)[signo-1].handler = (void *)sa.sa_sigaction;
		} else {
			SIGG(handlers)[signo-1].handler = (void *)sa.sa_handler;
		}

		sa.sa_flags     = SA_SIGINFO; /* we'll use a siginfo handler */
		sa.sa_sigaction = handler;
		sa.sa_mask      = global_sigmask;

		if (sigaction(signo, &sa, NULL) < 0) {
			zend_error_noreturn(E_ERROR, "Error installing signal handler for %d", signo);
		}

		return SUCCESS;
	}
	return FAILURE;
} /* }}} */
Beispiel #3
0
/* {{{ zend_implement_aggregate */
static int zend_implement_aggregate(zend_class_entry *interface, zend_class_entry *class_type)
{
	uint32_t i;
	int t = -1;

	if (class_type->get_iterator) {
		if (class_type->type == ZEND_INTERNAL_CLASS) {
			/* inheritance ensures the class has necessary userland methods */
			return SUCCESS;
		} else if (class_type->get_iterator != zend_user_it_get_new_iterator) {
			/* c-level get_iterator cannot be changed (exception being only Traversable is implmented) */
			if (class_type->num_interfaces) {
				for (i = 0; i < class_type->num_interfaces; i++) {
					if (class_type->interfaces[i] == zend_ce_iterator) {
						zend_error_noreturn(E_ERROR, "Class %s cannot implement both %s and %s at the same time",
									class_type->name->val,
									interface->name->val,
									zend_ce_iterator->name->val);
						return FAILURE;
					}
					if (class_type->interfaces[i] == zend_ce_traversable) {
						t = i;
					}
				}
			}
			if (t == -1) {
				return FAILURE;
			}
		}
	}
	class_type->iterator_funcs.zf_new_iterator = NULL;
	class_type->get_iterator = zend_user_it_get_new_iterator;
	return SUCCESS;
}
Beispiel #4
0
/* {{{ zend_implement_iterator */
static int zend_implement_iterator(zend_class_entry *interface, zend_class_entry *class_type)
{
	if (class_type->get_iterator && class_type->get_iterator != zend_user_it_get_iterator) {
		if (class_type->type == ZEND_INTERNAL_CLASS) {
			/* inheritance ensures the class has the necessary userland methods */
			return SUCCESS;
		} else {
			/* c-level get_iterator cannot be changed */
			if (class_type->get_iterator == zend_user_it_get_new_iterator) {
				zend_error_noreturn(E_ERROR, "Class %s cannot implement both %s and %s at the same time",
							class_type->name->val,
							interface->name->val,
							zend_ce_aggregate->name->val);
			}
			return FAILURE;
		}
	}
	class_type->get_iterator = zend_user_it_get_iterator;
	class_type->iterator_funcs.zf_valid = NULL;
	class_type->iterator_funcs.zf_current = NULL;
	class_type->iterator_funcs.zf_key = NULL;
	class_type->iterator_funcs.zf_next = NULL;
	class_type->iterator_funcs.zf_rewind = NULL;
	if (!class_type->iterator_funcs.funcs) {
		class_type->iterator_funcs.funcs = &zend_interface_iterator_funcs_iterator;
	}
	return SUCCESS;
}
Beispiel #5
0
void zend_exception_set_previous(zend_object *exception, zend_object *add_previous) /* {{{ */
{
    zval *previous, *ancestor, *ex;
	zval  pv, zv, rv;
	zend_class_entry *base_ce;

	if (exception == add_previous || !add_previous || !exception) {
		return;
	}
	ZVAL_OBJ(&pv, add_previous);
	if (!instanceof_function(Z_OBJCE(pv), zend_ce_throwable)) {
		zend_error_noreturn(E_CORE_ERROR, "Previous exception must implement Throwable");
		return;
	}
	ZVAL_OBJ(&zv, exception);
	ex = &zv;
	do {
		ancestor = zend_read_property_ex(i_get_exception_base(&pv), &pv, ZSTR_KNOWN(ZEND_STR_PREVIOUS), 1, &rv);
		while (Z_TYPE_P(ancestor) == IS_OBJECT) {
			if (Z_OBJ_P(ancestor) == Z_OBJ_P(ex)) {
				OBJ_RELEASE(add_previous);
				return;
			}
			ancestor = zend_read_property_ex(i_get_exception_base(ancestor), ancestor, ZSTR_KNOWN(ZEND_STR_PREVIOUS), 1, &rv);
		}
		base_ce = i_get_exception_base(ex);
		previous = zend_read_property_ex(base_ce, ex, ZSTR_KNOWN(ZEND_STR_PREVIOUS), 1, &rv);
		if (Z_TYPE_P(previous) == IS_NULL) {
			zend_update_property_ex(base_ce, ex, ZSTR_KNOWN(ZEND_STR_PREVIOUS), &pv);
			GC_DELREF(add_previous);
			return;
		}
		ex = previous;
	} while (Z_OBJ_P(ex) != add_previous);
}
Beispiel #6
0
/* {{{ zend_sigaction
 *  Register a signal handler that will be deferred in critical sections */
ZEND_API int zend_sigaction(int signo, const struct sigaction *act, struct sigaction *oldact)
{
	struct sigaction sa = {{0}};
	sigset_t sigset;

	if (oldact != NULL) {
		oldact->sa_flags   = SIGG(handlers)[signo-1].flags;
		oldact->sa_handler = (void *) SIGG(handlers)[signo-1].handler;
		oldact->sa_mask    = global_sigmask;
	}
	if (act != NULL) {
		SIGG(handlers)[signo-1].flags = act->sa_flags;
		if (act->sa_flags & SA_SIGINFO) {
			SIGG(handlers)[signo-1].handler = (void *) act->sa_sigaction;
		} else {
			SIGG(handlers)[signo-1].handler = (void *) act->sa_handler;
		}

		sa.sa_flags     = SA_SIGINFO | (act->sa_flags & SA_FLAGS_MASK);
		sa.sa_sigaction = zend_signal_handler_defer;
		sa.sa_mask      = global_sigmask;

		if (sigaction(signo, &sa, NULL) < 0) {
			zend_error_noreturn(E_ERROR, "Error installing signal handler for %d", signo);
		}

		/* unsure this signal is not blocked */
		sigemptyset(&sigset);
		sigaddset(&sigset, signo);
		zend_sigprocmask(SIG_UNBLOCK, &sigset, NULL);
	}

	return SUCCESS;
}
Beispiel #7
0
/* {{{ zend_implement_aggregate */
static int zend_implement_aggregate(zend_class_entry *interface, zend_class_entry *class_type)
{
	uint32_t i;
	int t = -1;
	zend_class_iterator_funcs *funcs_ptr;

	if (class_type->get_iterator) {
		if (class_type->type == ZEND_INTERNAL_CLASS) {
			/* inheritance ensures the class has necessary userland methods */
			return SUCCESS;
		} else if (class_type->get_iterator != zend_user_it_get_new_iterator) {
			/* c-level get_iterator cannot be changed (exception being only Traversable is implemented) */
			if (class_type->num_interfaces) {
				ZEND_ASSERT(class_type->ce_flags & (ZEND_ACC_LINKED|ZEND_ACC_LINKING_IN_PROGRESS));
				for (i = 0; i < class_type->num_interfaces; i++) {
					if (class_type->interfaces[i] == zend_ce_iterator) {
						zend_error_noreturn(E_ERROR, "Class %s cannot implement both %s and %s at the same time",
									ZSTR_VAL(class_type->name),
									ZSTR_VAL(interface->name),
									ZSTR_VAL(zend_ce_iterator->name));
						return FAILURE;
					}
					if (class_type->interfaces[i] == zend_ce_traversable) {
						t = i;
					}
				}
			}
			if (t == -1) {
				return FAILURE;
			}
		}
	}
	if (class_type->parent
	 && (class_type->parent->ce_flags & ZEND_ACC_REUSE_GET_ITERATOR)) {
		class_type->get_iterator = class_type->parent->get_iterator;
		class_type->ce_flags |= ZEND_ACC_REUSE_GET_ITERATOR;
	} else {
		class_type->get_iterator = zend_user_it_get_new_iterator;
	}
	funcs_ptr = class_type->iterator_funcs_ptr;
	if (class_type->type == ZEND_INTERNAL_CLASS) {
		if (!funcs_ptr) {
			funcs_ptr = calloc(1, sizeof(zend_class_iterator_funcs));
			class_type->iterator_funcs_ptr = funcs_ptr;
		}
		funcs_ptr->zf_new_iterator = zend_hash_str_find_ptr(&class_type->function_table, "getiterator", sizeof("getiterator") - 1);
	} else {
		if (!funcs_ptr) {
			funcs_ptr = zend_arena_alloc(&CG(arena), sizeof(zend_class_iterator_funcs));
			class_type->iterator_funcs_ptr = funcs_ptr;
			memset(funcs_ptr, 0, sizeof(zend_class_iterator_funcs));
		} else {
			funcs_ptr->zf_new_iterator = NULL;
		}
	}
	return SUCCESS;
}
Beispiel #8
0
/* {{{ unset an object property */
void pthreads_unset_property(PTHREADS_UNSET_PROPERTY_PASSTHRU_D) {
	PTHREAD pthreads = PTHREADS_FETCH_FROM(object);
	if (pthreads_store_delete(pthreads->store, Z_STRVAL_P(member), Z_STRLEN_P(member) TSRMLS_CC)!=SUCCESS){
		zend_error_noreturn(
			E_WARNING, 
			"pthreads has experienced an internal error while deleting %s::$%s", 
			Z_OBJCE_P(object)->name, Z_STRVAL_P(member)
		);
	}
	zend_handlers->unset_property(PTHREADS_UNSET_PROPERTY_PASSTHRU_C);
} 
Beispiel #9
0
/* {{{ zend_implement_iterator */
static int zend_implement_iterator(zend_class_entry *interface, zend_class_entry *class_type)
{
	zend_class_iterator_funcs *funcs_ptr;

	if (class_type->get_iterator && class_type->get_iterator != zend_user_it_get_iterator) {
		if (class_type->type == ZEND_INTERNAL_CLASS) {
			/* inheritance ensures the class has the necessary userland methods */
			return SUCCESS;
		} else {
			/* c-level get_iterator cannot be changed */
			if (class_type->get_iterator == zend_user_it_get_new_iterator) {
				zend_error_noreturn(E_ERROR, "Class %s cannot implement both %s and %s at the same time",
							ZSTR_VAL(class_type->name),
							ZSTR_VAL(interface->name),
							ZSTR_VAL(zend_ce_aggregate->name));
			}
			return FAILURE;
		}
	}
	if (class_type->parent
	 && (class_type->parent->ce_flags & ZEND_ACC_REUSE_GET_ITERATOR)) {
		class_type->get_iterator = class_type->parent->get_iterator;
		class_type->ce_flags |= ZEND_ACC_REUSE_GET_ITERATOR;
	} else {
		class_type->get_iterator = zend_user_it_get_iterator;
	}
	funcs_ptr = class_type->iterator_funcs_ptr;
	if (class_type->type == ZEND_INTERNAL_CLASS) {
		if (!funcs_ptr) {
			funcs_ptr = calloc(1, sizeof(zend_class_iterator_funcs));
			class_type->iterator_funcs_ptr = funcs_ptr;
		} else {
			funcs_ptr->zf_rewind = zend_hash_str_find_ptr(&class_type->function_table, "rewind", sizeof("rewind") - 1);
			funcs_ptr->zf_valid = zend_hash_str_find_ptr(&class_type->function_table, "valid", sizeof("valid") - 1);
			funcs_ptr->zf_key = zend_hash_str_find_ptr(&class_type->function_table, "key", sizeof("key") - 1);
			funcs_ptr->zf_current = zend_hash_str_find_ptr(&class_type->function_table, "current", sizeof("current") - 1);
			funcs_ptr->zf_next = zend_hash_str_find_ptr(&class_type->function_table, "next", sizeof("next") - 1);
		}
	} else {
		if (!funcs_ptr) {
			funcs_ptr = zend_arena_alloc(&CG(arena), sizeof(zend_class_iterator_funcs));
			class_type->iterator_funcs_ptr = funcs_ptr;
			memset(funcs_ptr, 0, sizeof(zend_class_iterator_funcs));
		} else {
			funcs_ptr->zf_valid = NULL;
			funcs_ptr->zf_current = NULL;
			funcs_ptr->zf_key = NULL;
			funcs_ptr->zf_next = NULL;
			funcs_ptr->zf_rewind = NULL;
		}
	}
	return SUCCESS;
}
Beispiel #10
0
/* {{{ zend_implement_throwable */
static int zend_implement_throwable(zend_class_entry *interface, zend_class_entry *class_type)
{
	if (instanceof_function(class_type, zend_ce_exception) || instanceof_function(class_type, zend_ce_error)) {
		return SUCCESS;
	}
	zend_error_noreturn(E_ERROR, "Class %s cannot implement interface %s, extend %s or %s instead",
		ZSTR_VAL(class_type->name),
		ZSTR_VAL(interface->name),
		ZSTR_VAL(zend_ce_exception->name),
		ZSTR_VAL(zend_ce_error->name));
	return FAILURE;
}
Beispiel #11
0
ZEND_API ZEND_COLD void zend_throw_exception_internal(zval *exception) /* {{{ */
{
#ifdef HAVE_DTRACE
	if (DTRACE_EXCEPTION_THROWN_ENABLED()) {
		if (exception != NULL) {
			DTRACE_EXCEPTION_THROWN(ZSTR_VAL(Z_OBJ_P(exception)->ce->name));
		} else {
			DTRACE_EXCEPTION_THROWN(NULL);
		}
	}
#endif /* HAVE_DTRACE */

	if (exception != NULL) {
		zend_object *previous = EG(exception);
		zend_exception_set_previous(Z_OBJ_P(exception), EG(exception));
		EG(exception) = Z_OBJ_P(exception);
		if (previous) {
			return;
		}
	}
	if (!EG(current_execute_data)) {
		if (exception && Z_OBJCE_P(exception) == zend_ce_parse_error) {
			return;
		}
		if(EG(exception)) {
			zend_exception_error(EG(exception), E_ERROR);
		}
		zend_error_noreturn(E_CORE_ERROR, "Exception thrown without a stack frame");
	}

	if (zend_throw_exception_hook) {
		zend_throw_exception_hook(exception);
	}

	if (!EG(current_execute_data)->func ||
	    !ZEND_USER_CODE(EG(current_execute_data)->func->common.type) ||
	    EG(current_execute_data)->opline->opcode == ZEND_HANDLE_EXCEPTION) {
		/* no need to rethrow the exception */
		return;
	}
	EG(opline_before_exception) = EG(current_execute_data)->opline;
	EG(current_execute_data)->opline = EG(exception_op);
}
Beispiel #12
0
ZEND_API void zval_internal_ptr_dtor(zval *zval_ptr) /* {{{ */
{
	if (Z_REFCOUNTED_P(zval_ptr)) {
		zend_refcounted *ref = Z_COUNTED_P(zval_ptr);

		if (GC_DELREF(ref) == 0) {
			if (Z_TYPE_P(zval_ptr) == IS_STRING) {
				zend_string *str = (zend_string*)ref;

				CHECK_ZVAL_STRING(str);
				ZEND_ASSERT(!ZSTR_IS_INTERNED(str));
				ZEND_ASSERT((GC_FLAGS(str) & IS_STR_PERSISTENT));
				free(str);
			} else {
				zend_error_noreturn(E_CORE_ERROR, "Internal zval's can't be arrays, objects, resources or reference");
			}
		}
	}
}
Beispiel #13
0
/* {{{ zend_implement_traversable */
static int zend_implement_traversable(zend_class_entry *interface, zend_class_entry *class_type)
{
	/* check that class_type is traversable at c-level or implements at least one of 'aggregate' and 'Iterator' */
	uint32_t i;

	if (class_type->get_iterator || (class_type->parent && class_type->parent->get_iterator)) {
		return SUCCESS;
	}
	for (i = 0; i < class_type->num_interfaces; i++) {
		if (class_type->interfaces[i] == zend_ce_aggregate || class_type->interfaces[i] == zend_ce_iterator) {
			return SUCCESS;
		}
	}
	zend_error_noreturn(E_CORE_ERROR, "Class %s must implement interface %s as part of either %s or %s",
		class_type->name->val,
		zend_ce_traversable->name->val,
		zend_ce_iterator->name->val,
		zend_ce_aggregate->name->val);
	return FAILURE;
}
Beispiel #14
0
/* {{{ zend_implement_traversable */
static int zend_implement_traversable(zend_class_entry *interface, zend_class_entry *class_type)
{
	/* check that class_type is traversable at c-level or implements at least one of 'aggregate' and 'Iterator' */
	uint32_t i;

	if (class_type->get_iterator || (class_type->parent && class_type->parent->get_iterator)) {
		return SUCCESS;
	}
	if (class_type->num_interfaces) {
		ZEND_ASSERT(class_type->ce_flags & (ZEND_ACC_LINKED|ZEND_ACC_LINKING_IN_PROGRESS));
		for (i = 0; i < class_type->num_interfaces; i++) {
			if (class_type->interfaces[i] == zend_ce_aggregate || class_type->interfaces[i] == zend_ce_iterator) {
				return SUCCESS;
			}
		}
	}
	zend_error_noreturn(E_CORE_ERROR, "Class %s must implement interface %s as part of either %s or %s",
		ZSTR_VAL(class_type->name),
		ZSTR_VAL(zend_ce_traversable->name),
		ZSTR_VAL(zend_ce_iterator->name),
		ZSTR_VAL(zend_ce_aggregate->name));
	return FAILURE;
}
Beispiel #15
0
/* {{{ writes a property to a thread in the appropriate way */
void pthreads_write_property(PTHREADS_WRITE_PROPERTY_PASSTHRU_D) {
	PTHREAD pthreads = PTHREADS_FETCH_FROM(object);
	if (Z_TYPE_P(member)==IS_STRING) {
		switch(Z_TYPE_P(value)){
			case IS_STRING:
			case IS_LONG:
			case IS_ARRAY:
			case IS_OBJECT:
			case IS_NULL:
			case IS_DOUBLE:
			case IS_BOOL: {
				if (pthreads_store_write(pthreads->store, Z_STRVAL_P(member), Z_STRLEN_P(member), &value TSRMLS_CC)!=SUCCESS){
					zend_error_noreturn(
						E_WARNING, 
						"pthreads failed to write member %s::$%s", 
						Z_OBJCE_P(object)->name, Z_STRVAL_P(member)
					);
				} else zend_handlers->write_property(PTHREADS_WRITE_PROPERTY_PASSTHRU_C);
			} break;
			
			default: zend_handlers->write_property(PTHREADS_WRITE_PROPERTY_PASSTHRU_C);
		}
	} else zend_handlers->write_property(PTHREADS_WRITE_PROPERTY_PASSTHRU_C);
} 
Beispiel #16
0
ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope, zend_ulong flags)
{
	zend_constant *c;
	const char *colon;
	zend_class_entry *ce = NULL;
	zend_string *class_name;
	const char *name = cname->val;
	size_t name_len = cname->len;

	/* Skip leading \\ */
	if (name[0] == '\\') {
		name += 1;
		name_len -= 1;
		cname = NULL;
	}

	if ((colon = zend_memrchr(name, ':', name_len)) &&
	    colon > name && (*(colon - 1) == ':')) {
		int class_name_len = colon - name - 1;
		size_t const_name_len = name_len - class_name_len - 2;
		zend_string *constant_name = zend_string_init(colon + 1, const_name_len, 0);
		char *lcname;
		zval *ret_constant = NULL;
		ALLOCA_FLAG(use_heap)

		class_name = zend_string_init(name, class_name_len, 0);
		lcname = do_alloca(class_name_len + 1, use_heap);
		zend_str_tolower_copy(lcname, name, class_name_len);
		if (!scope) {
			if (EG(current_execute_data)) {
				scope = EG(scope);
			} else {
				scope = CG(active_class_entry);
			}
		}

		if (class_name_len == sizeof("self")-1 &&
		    !memcmp(lcname, "self", sizeof("self")-1)) {
			if (scope) {
				ce = scope;
			} else {
				zend_error_noreturn(E_ERROR, "Cannot access self:: when no class scope is active");
			}
		} else if (class_name_len == sizeof("parent")-1 &&
		           !memcmp(lcname, "parent", sizeof("parent")-1)) {
			if (!scope) {
				zend_error_noreturn(E_ERROR, "Cannot access parent:: when no class scope is active");
			} else if (!scope->parent) {
				zend_error_noreturn(E_ERROR, "Cannot access parent:: when current class scope has no parent");
			} else {
				ce = scope->parent;
			}
		} else if (class_name_len == sizeof("static")-1 &&
		           !memcmp(lcname, "static", sizeof("static")-1)) {
			if (EG(current_execute_data) && EG(current_execute_data)->called_scope) {
				ce = EG(current_execute_data)->called_scope;
			} else {
				zend_error_noreturn(E_ERROR, "Cannot access static:: when no class scope is active");
			}
		} else {
			ce = zend_fetch_class(class_name, flags);
		}
		free_alloca(lcname, use_heap);
		if (ce) {
			ret_constant = zend_hash_find(&ce->constants_table, constant_name);
			if (ret_constant == NULL) {
				if ((flags & ZEND_FETCH_CLASS_SILENT) == 0) {
					zend_error_noreturn(E_ERROR, "Undefined class constant '%s::%s'", class_name->val, constant_name->val);
				}
			} else if (Z_ISREF_P(ret_constant)) {
				ret_constant = Z_REFVAL_P(ret_constant);
			}
		}
		zend_string_release(class_name);
		zend_string_free(constant_name);
		if (ret_constant && Z_CONSTANT_P(ret_constant)) {
			zval_update_constant_ex(ret_constant, 1, ce);
		}
		return ret_constant;
	}

	/* non-class constant */
	if ((colon = zend_memrchr(name, '\\', name_len)) != NULL) {
		/* compound constant name */
		int prefix_len = colon - name;
		size_t const_name_len = name_len - prefix_len - 1;
		const char *constant_name = colon + 1;
		char *lcname;
		size_t lcname_len;
		ALLOCA_FLAG(use_heap)

		lcname_len = prefix_len + 1 + const_name_len;
		lcname = do_alloca(lcname_len + 1, use_heap);
		zend_str_tolower_copy(lcname, name, prefix_len);
		/* Check for namespace constant */

		lcname[prefix_len] = '\\';
		memcpy(lcname + prefix_len + 1, constant_name, const_name_len + 1);

		if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, lcname_len)) == NULL) {
			/* try lowercase */
			zend_str_tolower(lcname + prefix_len + 1, const_name_len);
			if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, lcname_len)) != NULL) {
				if ((c->flags & CONST_CS) != 0) {
					c = NULL;
				}
			}
		}
		free_alloca(lcname, use_heap);
		if (c) {
			return &c->value;
		}
		/* name requires runtime resolution, need to check non-namespaced name */
		if ((flags & IS_CONSTANT_UNQUALIFIED) != 0) {
			return zend_get_constant_str(constant_name, const_name_len);
		}
		return NULL;
	}

	if (cname) {
		return zend_get_constant(cname);
	} else {
		return zend_get_constant_str(name, name_len);
	}
}
Beispiel #17
0
/* {{{ zend_call_method
 Only returns the returned zval if retval_ptr != NULL */
ZEND_API zval* zend_call_method(zend_object *object, zend_class_entry *obj_ce, zend_function **fn_proxy, const char *function_name, size_t function_name_len, zval *retval_ptr, int param_count, zval* arg1, zval* arg2)
{
	int result;
	zend_fcall_info fci;
	zval retval;
	zval params[2];

	if (param_count > 0) {
		ZVAL_COPY_VALUE(&params[0], arg1);
	}
	if (param_count > 1) {
		ZVAL_COPY_VALUE(&params[1], arg2);
	}

	fci.size = sizeof(fci);
	fci.object = object;
	fci.retval = retval_ptr ? retval_ptr : &retval;
	fci.param_count = param_count;
	fci.params = params;
	fci.no_separation = 1;

	if (!fn_proxy && !obj_ce) {
		/* no interest in caching and no information already present that is
		 * needed later inside zend_call_function. */
		ZVAL_STRINGL(&fci.function_name, function_name, function_name_len);
		result = zend_call_function(&fci, NULL);
		zval_ptr_dtor(&fci.function_name);
	} else {
		zend_fcall_info_cache fcic;
		ZVAL_UNDEF(&fci.function_name); /* Unused */

		if (!obj_ce) {
			obj_ce = object ? object->ce : NULL;
		}
		if (!fn_proxy || !*fn_proxy) {
			if (EXPECTED(obj_ce)) {
				fcic.function_handler = zend_hash_str_find_ptr(
					&obj_ce->function_table, function_name, function_name_len);
				if (UNEXPECTED(fcic.function_handler == NULL)) {
					/* error at c-level */
					zend_error_noreturn(E_CORE_ERROR, "Couldn't find implementation for method %s::%s", ZSTR_VAL(obj_ce->name), function_name);
				}
			} else {
				fcic.function_handler = zend_fetch_function_str(function_name, function_name_len);
				if (UNEXPECTED(fcic.function_handler == NULL)) {
					/* error at c-level */
					zend_error_noreturn(E_CORE_ERROR, "Couldn't find implementation for function %s", function_name);
				}
			}
			if (fn_proxy) {
				*fn_proxy = fcic.function_handler;
			}
		} else {
			fcic.function_handler = *fn_proxy;
		}

		if (object) {
			fcic.called_scope = object->ce;
		} else {
			zend_class_entry *called_scope = zend_get_called_scope(EG(current_execute_data));

			if (obj_ce &&
			    (!called_scope ||
			     !instanceof_function(called_scope, obj_ce))) {
				fcic.called_scope = obj_ce;
			} else {
				fcic.called_scope = called_scope;
			}
		}
		fcic.object = object;
		result = zend_call_function(&fci, &fcic);
	}
	if (result == FAILURE) {
		/* error at c-level */
		if (!obj_ce) {
			obj_ce = object ? object->ce : NULL;
		}
		if (!EG(exception)) {
			zend_error_noreturn(E_CORE_ERROR, "Couldn't execute method %s%s%s", obj_ce ? ZSTR_VAL(obj_ce->name) : "", obj_ce ? "::" : "", function_name);
		}
	}
	if (!retval_ptr) {
		zval_ptr_dtor(&retval);
		return NULL;
	}
	return retval_ptr;
}
Beispiel #18
0
/* {{{ zend_call_method
 Only returns the returned zval if retval_ptr != NULL */
ZEND_API zval* zend_call_method(zval *object, zend_class_entry *obj_ce, zend_function **fn_proxy, const char *function_name, size_t function_name_len, zval *retval_ptr, int param_count, zval* arg1, zval* arg2)
{
	int result;
	zend_fcall_info fci;
	zval retval;
	HashTable *function_table;

	zval params[2];

	if (param_count > 0) {
		ZVAL_COPY_VALUE(&params[0], arg1);
	}
	if (param_count > 1) {
		ZVAL_COPY_VALUE(&params[1], arg2);
	}

	fci.size = sizeof(fci);
	/*fci.function_table = NULL; will be read form zend_class_entry of object if needed */
	fci.object = (object && Z_TYPE_P(object) == IS_OBJECT) ? Z_OBJ_P(object) : NULL;
	ZVAL_STRINGL(&fci.function_name, function_name, function_name_len);
	fci.retval = retval_ptr ? retval_ptr : &retval;
	fci.param_count = param_count;
	fci.params = params;
	fci.no_separation = 1;
	fci.symbol_table = NULL;

	if (!fn_proxy && !obj_ce) {
		/* no interest in caching and no information already present that is
		 * needed later inside zend_call_function. */
		fci.function_table = !object ? EG(function_table) : NULL;
		result = zend_call_function(&fci, NULL);
		zval_ptr_dtor(&fci.function_name);
	} else {
		zend_fcall_info_cache fcic;

		fcic.initialized = 1;
		if (!obj_ce) {
			obj_ce = object ? Z_OBJCE_P(object) : NULL;
		}
		if (obj_ce) {
			function_table = &obj_ce->function_table;
		} else {
			function_table = EG(function_table);
		}
		if (!fn_proxy || !*fn_proxy) {
			if ((fcic.function_handler = zend_hash_find_ptr(function_table, Z_STR(fci.function_name))) == NULL) {
				/* error at c-level */
				zend_error_noreturn(E_CORE_ERROR, "Couldn't find implementation for method %s%s%s", obj_ce ? obj_ce->name->val : "", obj_ce ? "::" : "", function_name);
			}
			if (fn_proxy) {
				*fn_proxy = fcic.function_handler;
			}
		} else {
			fcic.function_handler = *fn_proxy;
		}
		fcic.calling_scope = obj_ce;
		if (object) {
			fcic.called_scope = Z_OBJCE_P(object);
		} else {
			zend_class_entry *called_scope = zend_get_called_scope(EG(current_execute_data));

			if (obj_ce &&
			    (!called_scope ||
			     !instanceof_function(called_scope, obj_ce))) {
				fcic.called_scope = obj_ce;
			} else {
				fcic.called_scope = called_scope;
			}
		}
		fcic.object = object ? Z_OBJ_P(object) : NULL;
		result = zend_call_function(&fci, &fcic);
		zval_ptr_dtor(&fci.function_name);
	}
	if (result == FAILURE) {
		/* error at c-level */
		if (!obj_ce) {
			obj_ce = object ? Z_OBJCE_P(object) : NULL;
		}
		if (!EG(exception)) {
			zend_error_noreturn(E_CORE_ERROR, "Couldn't execute method %s%s%s", obj_ce ? obj_ce->name->val : "", obj_ce ? "::" : "", function_name);
		}
	}
	/* copy arguments back, they might be changed by references */
	if (param_count > 0 && Z_ISREF(params[0]) && !Z_ISREF_P(arg1)) {
		ZVAL_COPY_VALUE(arg1, &params[0]);
	}
	if (param_count > 1 && Z_ISREF(params[1]) && !Z_ISREF_P(arg2)) {
		ZVAL_COPY_VALUE(arg2, &params[1]);
	}
	if (!retval_ptr) {
		zval_ptr_dtor(&retval);
		return NULL;
	}
	return retval_ptr;
}
Beispiel #19
0
/* {{{ pthreads_call_method */
int pthreads_call_method(PTHREADS_CALL_METHOD_PASSTHRU_D) {
	zval 					***argv = NULL, zmethod, *zresult;
	zend_function 			*call = NULL;
	zend_fcall_info 		info;
	zend_fcall_info_cache	cache;
	zend_class_entry		*scope;
	int 					called = -1, argc = ZEND_NUM_ARGS(), access = ZEND_ACC_PUBLIC, mlength = 0;
	char					*lcname;
	zend_bool				unprotect;
	
	if (getThis()) {
		PTHREAD thread = PTHREADS_FETCH;
		if (thread) {
			switch((access=pthreads_modifiers_get(thread->modifiers, method TSRMLS_CC))){
				case ZEND_ACC_PRIVATE:
				case ZEND_ACC_PROTECTED: {
					scope = Z_OBJCE_P(getThis());
					
					/*
					* Stop invalid private method calls
					*/
					if (access == ZEND_ACC_PRIVATE && !PTHREADS_IN_THREAD(thread)) {
						zend_error_noreturn(
							E_ERROR, 
							"pthreads detected an attempt to call private method %s::%s from outside the threading context", 
							scope->name,
							method
						);
						return FAILURE;
					}
					
					/*
					* Get arguments from stack
					*/
					if (ZEND_NUM_ARGS()) 
					{
						argv = safe_emalloc(sizeof(zval **), argc, 0);
						if (argv) {
							zend_get_parameters_array_ex(argc, argv);
						}
					}
							
					mlength = strlen(method);
					lcname =  calloc(1, mlength+1);
					zend_str_tolower_copy(lcname, method, mlength);
					
					if (zend_hash_find(&scope->function_table, lcname, mlength+1, (void**)&call)==SUCCESS) {
						if (call) {
							/*
							* Make protected method call
							*/
							{
								if (access != ZEND_ACC_PROTECTED || pthreads_modifiers_protect(thread->modifiers, method, &unprotect TSRMLS_CC)) {
								
									ZVAL_STRINGL(&zmethod, method, strlen(method), 0);
									
									info.size = sizeof(info);
									info.object_ptr = getThis();
									info.function_name = &zmethod;
									info.retval_ptr_ptr = &zresult;
									info.no_separation = 1;
									info.symbol_table = NULL;
									info.param_count = argc;
									info.params = argv;
									
									cache.initialized = 1;
									cache.function_handler = call;
									cache.calling_scope = EG(called_scope);
									cache.called_scope = scope;
									cache.object_ptr = getThis();
									
									if ((called=zend_call_function(&info, &cache TSRMLS_CC))!=SUCCESS) {
										zend_error_noreturn(
											E_ERROR, 
											"pthreads has experienced an internal error while calling %s method %s::%s and cannot continue", 
											(access == ZEND_ACC_PROTECTED) ? "protected" : "private",
											scope->name,
											method
										);
									} else {
#if PHP_VERSION_ID > 50399
										{
											zend_op_array *ops = (zend_op_array*) call;
										
											if (ops) {
												if (ops->run_time_cache) {
													efree(ops->run_time_cache);
													ops->run_time_cache = NULL;
												}
											}
										}
#endif
										if (!return_value_used) {
											zval_ptr_dtor(&zresult);
										} else {
											ZVAL_ZVAL(return_value, zresult, 1, 1);
										}
									}
									
									if (access == ZEND_ACC_PROTECTED) {
										pthreads_modifiers_unprotect(thread->modifiers, method, unprotect TSRMLS_CC);
									}
								} else {
									zend_error_noreturn(
										E_ERROR, 
										"pthreads has experienced an internal error while calling %s method %s::%s and cannot continue", 
										(access == ZEND_ACC_PROTECTED) ? "protected" : "private",
										scope->name,
										method
									);
									called = FAILURE;
								}
							}
						} else {
							zend_error_noreturn(
								E_ERROR, 
								"pthreads has experienced an internal error while finding %s method %s::%s and cannot continue", 
								(access == ZEND_ACC_PROTECTED) ? "protected" : "private",
								scope->name,
								method
							);
							called = FAILURE;
						}
					}
					/*
					* Free unstacked arguments
					*/
					if (argc) {
						efree(argv);
					}
					free(lcname);
					return called;
				} break;
			}
		}
	}
	
	switch (called) {
		case -1: 
			return zend_handlers->call_method(PTHREADS_CALL_METHOD_PASSTHRU_C);
			
		default: return called;
	}
	
} /* }}} */
Beispiel #20
0
static void dic_optimizer_get_handler(INTERNAL_FUNCTION_PARAMETERS)
{
	char *id, should_free = 1;
	zend_ulong id_hash;
	int id_len, i;
	long oninvalid, exception_on_invalid_reference_const;
	zval **found_service, **alias, **method_in_map = NULL, *this_services, *this_aliases, *this_methodMap, *this_loading;
	zend_function *method = NULL;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &id, &id_len, &oninvalid) == FAILURE) {
		return;
	}

	if (strcasecmp(id, "service_container") == 0) {
		RETURN_THIS;
	}

	this_services  = zend_read_property(Z_OBJCE_P(getThis()), getThis(), SYMFONY_DIC_TOKEN_SERVICES_KEY, sizeof(SYMFONY_DIC_TOKEN_SERVICES_KEY) - 1, 0 TSRMLS_CC);
	this_aliases   = zend_read_property(Z_OBJCE_P(getThis()), getThis(), SYMFONY_DIC_TOKEN_ALIASES_KEY, sizeof(SYMFONY_DIC_TOKEN_ALIASES_KEY) - 1, 0 TSRMLS_CC);
	this_loading   = zend_read_property(Z_OBJCE_P(getThis()), getThis(), SYMFONY_DIC_TOKEN_LOADING_KEY, sizeof(SYMFONY_DIC_TOKEN_LOADING_KEY) - 1, 0 TSRMLS_CC);
	this_methodMap = zend_read_property(Z_OBJCE_P(getThis()), getThis(), SYMFONY_DIC_TOKEN_METHODMAP_KEY, sizeof(SYMFONY_DIC_TOKEN_METHODMAP_KEY) - 1, 0 TSRMLS_CC);

	if (!SYMFONY_DIC_G(cache_done)) {
		zval invalidBehavior;
		zend_class_entry **exception_ce;

		zend_get_constant_ex("self::EXCEPTION_ON_INVALID_REFERENCE", sizeof("self::EXCEPTION_ON_INVALID_REFERENCE") - 1, &invalidBehavior, Z_OBJCE_P(getThis()), 0  TSRMLS_CC);
		SYMFONY_DIC_G(invalid_behavior) = Z_LVAL(invalidBehavior);

		if (FAILURE == zend_lookup_class(SYMFONY_DIC_TOKEN_SERVICE_CIRCULAR_REFERENCE_EXCEPTION_KEY_UP, sizeof(SYMFONY_DIC_TOKEN_SERVICE_CIRCULAR_REFERENCE_EXCEPTION_KEY_UP) - 1, &exception_ce TSRMLS_CC)) {
			zend_error_noreturn(E_ERROR, "Class %s not found", SYMFONY_DIC_TOKEN_SERVICE_CIRCULAR_REFERENCE_EXCEPTION_KEY_UP);
		}
		SYMFONY_DIC_G(ServiceCircularReferenceException) = *exception_ce;
		if (FAILURE == zend_lookup_class(SYMFONY_DIC_TOKEN_SERVICE_NOT_FOUND_EXCEPTION_KEY_UP, sizeof(SYMFONY_DIC_TOKEN_SERVICE_NOT_FOUND_EXCEPTION_KEY_UP) - 1, &exception_ce TSRMLS_CC)) {
			zend_error_noreturn(E_ERROR, "Class %s not found", SYMFONY_DIC_TOKEN_SERVICE_NOT_FOUND_EXCEPTION_KEY_UP);
		}
		SYMFONY_DIC_G(ServiceNotFoundException) = *exception_ce;
		if (FAILURE == zend_lookup_class(SYMFONY_DIC_TOKEN_INACTIVE_SCOPE_EXCEPTION_KEY_UP, sizeof(SYMFONY_DIC_TOKEN_INACTIVE_SCOPE_EXCEPTION_KEY_UP) - 1, &exception_ce TSRMLS_CC)) {
			zend_error_noreturn(E_ERROR, "Class %s not found", SYMFONY_DIC_TOKEN_INACTIVE_SCOPE_EXCEPTION_KEY_UP);
		}
		SYMFONY_DIC_G(InactiveScopeException) = *exception_ce;

		SYMFONY_DIC_G(cache_done) = 1;
	}

	exception_on_invalid_reference_const = SYMFONY_DIC_G(invalid_behavior);

	if (ZEND_NUM_ARGS() <= 1) {
		oninvalid = exception_on_invalid_reference_const;
	}

	if (IS_INTERNED(id)) {
		id_hash = INTERNED_HASH(id);
	} else {
		id_hash = zend_inline_hash_func(id, id_len + 1);
	}

	id = estrndup(id, id_len); /* zend_str_tolower will change it otherwise */

	for (i = 0; i <= 1; i++, zend_str_tolower(id, id_len), id_hash = zend_inline_hash_func(id, id_len + 1)) {
		if (zend_hash_quick_find(Z_ARRVAL_P(this_aliases), id, id_len + 1, id_hash, (void **)&alias) == SUCCESS) {
			should_free = 0;
			efree(id);
			id      = Z_STRVAL_PP(alias);
			id_len  = Z_STRLEN_PP(alias);
			id_hash = zend_inline_hash_func(id, id_len + 1);
		}
		if (zend_hash_quick_find(Z_ARRVAL_P(this_services), id, id_len + 1, id_hash, (void **)&found_service) == SUCCESS) {
			RETVAL_ZVAL_FAST(*found_service);
			goto free_and_return;
		}
	}

	if (zend_hash_quick_exists(Z_ARRVAL_P(this_loading), id, id_len + 1, id_hash)) {
		zval *ServiceCircularReferenceException;
		ALLOC_INIT_ZVAL(ServiceCircularReferenceException); /* ctor_args */
		object_init_ex(ServiceCircularReferenceException, SYMFONY_DIC_G(ServiceCircularReferenceException));
		zend_throw_exception_object(ServiceCircularReferenceException TSRMLS_CC);
		goto free_and_return;
	}

	zend_hash_quick_find(Z_ARRVAL_P(this_methodMap), id, id_len + 1, id_hash, (void **)&method_in_map);

	if (!method_in_map) {
		char *new_id;

		for (i=0; i < id_len; i++) {
			if (id[i] == '_') {
				memmove(&id[i], &id[i + 1], --id_len);
			}
		}
		php_strtr(id, id_len, ".\\", "__", 2);
		id_len = spprintf(&new_id, 0, "get%sservice", id);
		efree(id);
		id      = new_id;
		id_hash = zend_inline_hash_func(id, id_len + 1);

		zend_hash_quick_find(&Z_OBJCE_P(getThis())->function_table, id, id_len + 1, id_hash, (void **)&method);
		if (!method) {
			if (oninvalid == exception_on_invalid_reference_const) {
				zval *ServiceNotFoundException;
				ALLOC_INIT_ZVAL(ServiceNotFoundException);
				object_init_ex(ServiceNotFoundException, SYMFONY_DIC_G(ServiceNotFoundException));
				zend_throw_exception_object(ServiceNotFoundException TSRMLS_CC); /* ctor_args */
			}
			goto free_and_return;
		}
	} else {
		char *method_name_lc;
		method_name_lc = zend_str_tolower_dup(Z_STRVAL_PP(method_in_map), Z_STRLEN_PP(method_in_map));
		zend_hash_find(&Z_OBJCE_P(getThis())->function_table, method_name_lc, Z_STRLEN_PP(method_in_map) + 1, (void **)&method);
		efree(method_name_lc);
	}

	zend_fcall_info fci = {0};
	zend_fcall_info_cache fcic = {0};
	zval *loading, *result;

	ALLOC_INIT_ZVAL(loading); ZVAL_BOOL(loading, 1);
	zend_hash_quick_add(Z_ARRVAL_P(this_loading), id, id_len + 1, id_hash, &loading, sizeof(zval *), NULL);

	fcic.called_scope = Z_OBJCE_P(getThis());
	fcic.calling_scope = Z_OBJCE_P(getThis());
	fcic.function_handler = method;
	fcic.initialized = 1;
	fcic.object_ptr = getThis();

	fci.retval_ptr_ptr = &result;
	fci.size = sizeof(zend_fcall_info);

	zend_call_function(&fci, &fcic TSRMLS_CC);

	zend_hash_quick_del(Z_ARRVAL_P(this_loading), id, id_len + 1, id_hash);

	if (!EG(exception)) {
		RETVAL_ZVAL_FAST(result);
	} else {
		zend_hash_quick_del(Z_ARRVAL_P(this_services), id, id_len, id_hash);

		if (instanceof_function(Z_OBJCE_P(EG(exception)), SYMFONY_DIC_G(InactiveScopeException) TSRMLS_CC) && oninvalid == exception_on_invalid_reference_const) {
			EG(exception) = NULL;
		}
	}
	zval_ptr_dtor(&result);
free_and_return:
	if (should_free) { efree(id); }
	return;
}
Beispiel #21
0
apc_segment_t apc_mmap(char *file_mask, size_t size)
{
	apc_segment_t segment;

	int fd = -1;
	int flags = MAP_SHARED | MAP_NOSYNC;
#ifdef APC_MEMPROTECT
	int remap = 1;
#endif

	/* If no filename was provided, do an anonymous mmap */
	if(!file_mask || (file_mask && !strlen(file_mask))) {
#if !defined(MAP_ANON)
		zend_error_noreturn(E_CORE_ERROR, "Anonymous mmap does not appear to be available on this system (MAP_ANON/MAP_ANONYMOUS).  Please see the apc.mmap_file_mask INI option.");
#else
		fd = -1;
		flags = MAP_SHARED | MAP_ANON;
#ifdef APC_MEMPROTECT
		remap = 0;
#endif
#endif
	} else if(!strcmp(file_mask,"/dev/zero")) {
		fd = open("/dev/zero", O_RDWR, S_IRUSR | S_IWUSR);
		if(fd == -1) {
			zend_error_noreturn(E_CORE_ERROR, "apc_mmap: open on /dev/zero failed");
		}
#ifdef APC_MEMPROTECT
		remap = 0; /* cannot remap */
#endif
	} else {
		/*
		 * Otherwise we do a normal filesystem mmap
		 */
		fd = mkstemp(file_mask);
		if(fd == -1) {
			zend_error_noreturn(E_CORE_ERROR, "apc_mmap: mkstemp on %s failed", file_mask);
		}
		if (ftruncate(fd, size) < 0) {
			close(fd);
			unlink(file_mask);
			zend_error_noreturn(E_CORE_ERROR, "apc_mmap: ftruncate failed");
		}
		unlink(file_mask);
	}

	segment.shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, flags, fd, 0);
	segment.size = size;

#ifdef APC_MEMPROTECT
	if(remap) {
		segment.roaddr = (void *)mmap(NULL, size, PROT_READ, flags, fd, 0);
	} else {
		segment.roaddr = NULL;
	}
#endif

	if ((long)segment.shmaddr == -1) {
		zend_error_noreturn(E_CORE_ERROR, "apc_mmap: Failed to mmap %zu bytes. Is your apc.shm_size too large?", size);
	}

	if (fd != -1) close(fd);

	return segment;
}