Index: php5-5.3.3.1/Zend/zend_API.c
===================================================================
--- php5-5.3.3.1.orig/Zend/zend_API.c	2015-08-29 12:02:15.000000000 +0200
+++ php5-5.3.3.1/Zend/zend_API.c	2015-08-29 12:08:57.000000000 +0200
@@ -251,54 +251,63 @@
 }
 /* }}} */
 
-static int parse_arg_object_to_string(zval **arg TSRMLS_DC) /* {{{ */
+static int parse_arg_object_to_string(zval **arg, char **p, int *pl, int type TSRMLS_DC) /* {{{ */
 {
-	if (Z_OBJ_HANDLER_PP(arg, cast_object)) {
-		SEPARATE_ZVAL_IF_NOT_REF(arg);
-		if (Z_OBJ_HANDLER_PP(arg, cast_object)(*arg, *arg, IS_STRING TSRMLS_CC) == SUCCESS) {
-			return SUCCESS;
-		}
-	}
-	/* Standard PHP objects */
-	if (Z_OBJ_HT_PP(arg) == &std_object_handlers || !Z_OBJ_HANDLER_PP(arg, cast_object)) {
-		SEPARATE_ZVAL_IF_NOT_REF(arg);
-		if (zend_std_cast_object_tostring(*arg, *arg, IS_STRING TSRMLS_CC) == SUCCESS) {
-			return SUCCESS;
-		}
-	}
-	if (!Z_OBJ_HANDLER_PP(arg, cast_object) && Z_OBJ_HANDLER_PP(arg, get)) {
-		int use_copy;
-		zval *z = Z_OBJ_HANDLER_PP(arg, get)(*arg TSRMLS_CC);
-		Z_ADDREF_P(z);
-		if(Z_TYPE_P(z) != IS_OBJECT) {
-			zval_dtor(*arg);
-			Z_TYPE_P(*arg) = IS_NULL;
-			zend_make_printable_zval(z, *arg, &use_copy);
-			if (!use_copy) {
-				ZVAL_ZVAL(*arg, z, 1, 1);
-			}
-			return SUCCESS;
-		}
-		zval_ptr_dtor(&z);
-	}
-	return FAILURE;
+        if (Z_OBJ_HANDLER_PP(arg, cast_object)) {
+                zval *obj;
+                MAKE_STD_ZVAL(obj);
+                if (Z_OBJ_HANDLER_P(*arg, cast_object)(*arg, obj, type TSRMLS_CC) == SUCCESS) {
+                        zval_ptr_dtor(arg);
+                        *arg = obj;
+                        *pl = Z_STRLEN_PP(arg);
+                        *p = Z_STRVAL_PP(arg);
+                        return SUCCESS;
+                }
+                efree(obj);
+        }
+        /* Standard PHP objects */
+        if (Z_OBJ_HT_PP(arg) == &std_object_handlers || !Z_OBJ_HANDLER_PP(arg, cast_object)) {
+                SEPARATE_ZVAL_IF_NOT_REF(arg);
+                if (zend_std_cast_object_tostring(*arg, *arg, type TSRMLS_CC) == SUCCESS) {
+                        *pl = Z_STRLEN_PP(arg);
+                        *p = Z_STRVAL_PP(arg);
+                        return SUCCESS;
+                }
+        }
+        if (!Z_OBJ_HANDLER_PP(arg, cast_object) && Z_OBJ_HANDLER_PP(arg, get)) {
+                int use_copy;
+                zval *z = Z_OBJ_HANDLER_PP(arg, get)(*arg TSRMLS_CC);
+                Z_ADDREF_P(z);
+                if(Z_TYPE_P(z) != IS_OBJECT) {
+                        zval_dtor(*arg);
+                        Z_TYPE_P(*arg) = IS_NULL;
+                        zend_make_printable_zval(z, *arg, &use_copy);
+                        if (!use_copy) {
+                                ZVAL_ZVAL(*arg, z, 1, 1);
+                        }
+                        *pl = Z_STRLEN_PP(arg);
+                        *p = Z_STRVAL_PP(arg);
+                        return SUCCESS;
+                }
+                zval_ptr_dtor(&z);
+        }
+        return FAILURE;
 }
 /* }}} */
 
-static char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, char **spec, char **error, int *severity TSRMLS_DC) /* {{{ */
+
+static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, const char **spec, char **error, int *severity TSRMLS_DC) /* {{{ */
 {
-	char *spec_walk = *spec;
+	const char *spec_walk = *spec;
 	char c = *spec_walk++;
-	int return_null = 0;
+	int check_null = 0;
 
 	/* scan through modifiers */
 	while (1) {
 		if (*spec_walk == '/') {
 			SEPARATE_ZVAL_IF_NOT_REF(arg);
 		} else if (*spec_walk == '!') {
-			if (Z_TYPE_PP(arg) == IS_NULL) {
-				return_null = 1;
-			}
+			check_null = 1;
 		} else {
 			break;
 		}
@@ -310,6 +319,12 @@
 		case 'L':
 			{
 				long *p = va_arg(*va, long *);
+
+				if (check_null) {
+					zend_bool *p = va_arg(*va, zend_bool *);
+					*p = (Z_TYPE_PP(arg) == IS_NULL);
+				}
+
 				switch (Z_TYPE_PP(arg)) {
 					case IS_STRING:
 						{
@@ -363,6 +378,12 @@
 		case 'd':
 			{
 				double *p = va_arg(*va, double *);
+
+				if (check_null) {
+					zend_bool *p = va_arg(*va, zend_bool *);
+					*p = (Z_TYPE_PP(arg) == IS_NULL);
+				}
+
 				switch (Z_TYPE_PP(arg)) {
 					case IS_STRING:
 						{
@@ -394,13 +415,14 @@
 			}
 			break;
 
+		case 'p':
 		case 's':
 			{
 				char **p = va_arg(*va, char **);
 				int *pl = va_arg(*va, int *);
 				switch (Z_TYPE_PP(arg)) {
 					case IS_NULL:
-						if (return_null) {
+						if (check_null) {
 							*p = NULL;
 							*pl = 0;
 							break;
@@ -420,13 +442,23 @@
 						}
 						*p = Z_STRVAL_PP(arg);
 						*pl = Z_STRLEN_PP(arg);
+						if (c == 'p' && CHECK_ZVAL_NULL_PATH(*arg)) {
+							return "a valid path";
+						}
 						break;
 
 					case IS_OBJECT:
+						if (parse_arg_object_to_string(arg, p, pl, IS_STRING TSRMLS_CC) == SUCCESS) {
+							if (c == 'p' && CHECK_ZVAL_NULL_PATH(*arg)) {
+								return "a valid path";
+							}
+							break;
+						}
+
 					case IS_ARRAY:
 					case IS_RESOURCE:
 					default:
-						return "string";
+						return c == 's' ? "string" : "a valid path";
 				}
 			}
 			break;
@@ -434,6 +466,12 @@
 		case 'b':
 			{
 				zend_bool *p = va_arg(*va, zend_bool *);
+
+				if (check_null) {
+					zend_bool *p = va_arg(*va, zend_bool *);
+					*p = (Z_TYPE_PP(arg) == IS_NULL);
+				}
+
 				switch (Z_TYPE_PP(arg)) {
 					case IS_NULL:
 					case IS_STRING:
@@ -456,7 +494,7 @@
 		case 'r':
 			{
 				zval **p = va_arg(*va, zval **);
-				if (return_null) {
+				if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
 					*p = NULL;
 					break;
 				}
@@ -471,7 +509,7 @@
 		case 'a':
 			{
 				zval **p = va_arg(*va, zval **);
-				if (return_null) {
+				if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
 					*p = NULL;
 					break;
 				}
@@ -486,7 +524,7 @@
 		case 'h':
 			{
 				HashTable **p = va_arg(*va, HashTable **);
-				if (return_null) {
+				if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
 					*p = NULL;
 					break;
 				}
@@ -506,7 +544,7 @@
 		case 'o':
 			{
 				zval **p = va_arg(*va, zval **);
-				if (return_null) {
+				if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
 					*p = NULL;
 					break;
 				}
@@ -523,7 +561,7 @@
 				zval **p = va_arg(*va, zval **);
 				zend_class_entry *ce = va_arg(*va, zend_class_entry *);
 
-				if (return_null) {
+				if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
 					*p = NULL;
 					break;
 				}
@@ -545,7 +583,7 @@
 				zend_class_entry **lookup, **pce = va_arg(*va, zend_class_entry **);
 				zend_class_entry *ce_base = *pce;
 
-				if (return_null) {
+				if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
 					*pce = NULL;
 					break;
 				}
@@ -579,7 +617,7 @@
 				zend_fcall_info_cache *fcc = va_arg(*va, zend_fcall_info_cache *);
 				char *is_callable_error = NULL;
 
-				if (return_null) {
+				if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
 					fci->size = 0;
 					fcc->initialized = 0;
 					break;
@@ -609,7 +647,7 @@
 		case 'z':
 			{
 				zval **p = va_arg(*va, zval **);
-				if (return_null) {
+				if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
 					*p = NULL;
 				} else {
 					*p = *arg;
@@ -620,7 +658,7 @@
 		case 'Z':
 			{
 				zval ***p = va_arg(*va, zval ***);
-				if (return_null) {
+				if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
 					*p = NULL;
 				} else {
 					*p = arg;
@@ -638,16 +676,17 @@
 }
 /* }}} */
 
-static int zend_parse_arg(int arg_num, zval **arg, va_list *va, char **spec, int quiet TSRMLS_DC) /* {{{ */
+static int zend_parse_arg(int arg_num, zval **arg, va_list *va, const char **spec, int quiet TSRMLS_DC) /* {{{ */
 {
-	char *expected_type = NULL, *error = NULL;
+	const char *expected_type = NULL;
+	char *error = NULL;
 	int severity = E_WARNING;
 
 	expected_type = zend_parse_arg_impl(arg_num, arg, va, spec, &error, &severity TSRMLS_CC);
 	if (expected_type) {
 		if (!quiet && (*expected_type || error)) {
-			char *space;
-			char *class_name = get_active_class_name(&space TSRMLS_CC);
+			const char *space;
+			const char *class_name = get_active_class_name(&space TSRMLS_CC);
 
 			if (error) {
 				zend_error(severity, "%s%s%s() expects parameter %d %s",
@@ -668,15 +707,28 @@
 }
 /* }}} */
 
-static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int flags TSRMLS_DC) /* {{{ */
+ZEND_API int zend_parse_parameter(int flags, int arg_num TSRMLS_DC, zval **arg, const char *spec, ...)
+{
+	va_list va;
+	int ret;
+	int quiet = flags & ZEND_PARSE_PARAMS_QUIET;
+
+	va_start(va, spec);
+	ret = zend_parse_arg(arg_num, arg, &va, &spec, quiet TSRMLS_CC);
+	va_end(va);
+
+	return ret;
+}
+
+static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va, int flags TSRMLS_DC) /* {{{ */
 {
-	char *spec_walk;
+	const  char *spec_walk;
 	int c, i;
 	int min_num_args = -1;
 	int max_num_args = 0;
 	int post_varargs = 0;
 	zval **arg;
-	int arg_count = (int)(zend_uintptr_t) *(zend_vm_stack_top(TSRMLS_C) - 1);
+	int arg_count;
 	int quiet = flags & ZEND_PARSE_PARAMS_QUIET;
 	zend_bool have_varargs = 0;
 	zval ****varargs = NULL;
@@ -685,21 +737,14 @@
 	for (spec_walk = type_spec; *spec_walk; spec_walk++) {
 		c = *spec_walk;
 		switch (c) {
-			case 's':
-				if (max_num_args < arg_count) {
-					arg = (zval **) (zend_vm_stack_top(TSRMLS_C) - 1 - (arg_count - max_num_args));
-					if (Z_TYPE_PP(arg) == IS_OBJECT) {
-						parse_arg_object_to_string(arg TSRMLS_CC);
-					}
-				}
-				/* break missing intentionally */
 			case 'l': case 'd':
-			case 'H': case 'b':
+			case 's': case 'b':
 			case 'r': case 'a':
 			case 'o': case 'O':
 			case 'z': case 'Z':
 			case 'C': case 'h':
 			case 'f': case 'A':
+			case 'H': case 'p':
 				max_num_args++;
 				break;
 
@@ -717,7 +762,7 @@
 				if (have_varargs) {
 					if (!quiet) {
 						zend_function *active_function = EG(current_execute_data)->function_state.function;
-						char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
+						const char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
 						zend_error(E_WARNING, "%s%s%s(): only one varargs specifier (* or +) is permitted",
 								class_name,
 								class_name[0] ? "::" : "",
@@ -737,7 +782,7 @@
 			default:
 				if (!quiet) {
 					zend_function *active_function = EG(current_execute_data)->function_state.function;
-					char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
+					const char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
 					zend_error(E_WARNING, "%s%s%s(): bad type specifier while parsing parameters",
 							class_name,
 							class_name[0] ? "::" : "",
@@ -760,7 +805,7 @@
 	if (num_args < min_num_args || (num_args > max_num_args && max_num_args > 0)) {
 		if (!quiet) {
 			zend_function *active_function = EG(current_execute_data)->function_state.function;
-			char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
+			const char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
 			zend_error(E_WARNING, "%s%s%s() expects %s %d parameter%s, %d given",
 					class_name,
 					class_name[0] ? "::" : "",
@@ -773,6 +818,8 @@
 		return FAILURE;
 	}
 
+	arg_count = (int)(zend_uintptr_t) *(zend_vm_stack_top(TSRMLS_C) - 1);
+
 	if (num_args > arg_count) {
 		zend_error(E_WARNING, "%s(): could not obtain parameters for parsing",
 			get_active_function_name(TSRMLS_C));
Index: php5-5.3.3.1/Zend/zend_API.h
===================================================================
--- php5-5.3.3.1.orig/Zend/zend_API.h	2015-07-28 15:35:15.000000000 +0200
+++ php5-5.3.3.1/Zend/zend_API.h	2015-08-29 12:05:31.000000000 +0200
@@ -510,6 +510,9 @@
 #define CHECK_ZVAL_STRING_REL(z)
 #endif
 
+#define CHECK_ZVAL_NULL_PATH(p) (Z_STRLEN_P(p) != strlen(Z_STRVAL_P(p)))
+#define CHECK_NULL_PATH(p, l) (strlen(p) != l)
+
 #define ZVAL_RESOURCE(z, l) {		\
 		Z_TYPE_P(z) = IS_RESOURCE;	\
 		Z_LVAL_P(z) = l;			\
