summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/standard/var_unserializer.c39
-rw-r--r--main/main.c1
-rw-r--r--main/php_globals.h2
-rw-r--r--php.ini-dist9
4 files changed, 46 insertions, 5 deletions
diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c
index cbc00fbb19..ef3f2b8d57 100644
--- a/ext/standard/var_unserializer.c
+++ b/ext/standard/var_unserializer.c
@@ -371,6 +371,13 @@ yy20:
zend_class_entry *ce;
int incomplete_class = 0;
+ char *rval_temp;
+
+ zval *user_func;
+ zval *retval_ptr;
+ zval **args[1];
+ zval *arg_func_name;
+
INIT_PZVAL(*rval);
len2 = len = parse_iv(start + 2);
if (len == 0)
@@ -385,12 +392,34 @@ yy20:
}
}
- if (zend_hash_find(EG(class_table), class_name, len2 + 1, (void **) &ce) != SUCCESS) {
- incomplete_class = 1;
- ce = PHP_IC_ENTRY;
- } else
+ if (zend_hash_find(CG(class_table), class_name, len2 + 1, (void **) &ce) != SUCCESS) {
+ if (PG(unserialize_callback_func) == NULL) {
+ incomplete_class = 1;
+ ce = PHP_IC_ENTRY;
+ } else {
+ MAKE_STD_ZVAL(user_func);
+ ZVAL_STRING(user_func, PG(unserialize_callback_func), 1);
+
+ args[0] = &arg_func_name;
+ MAKE_STD_ZVAL(arg_func_name);
+ ZVAL_STRING(arg_func_name, class_name, 1);
+
+ if (call_user_function_ex(CG(function_table), NULL, user_func, &retval_ptr, 1, args, 0, NULL TSRMLS_CC) != SUCCESS) {
+ zend_error(E_WARNING, "'unserialize_callback_func' defined (%s) but not found", user_func->value.str.val);
+ incomplete_class = 1;
+ ce = PHP_IC_ENTRY;
+ } else {
+ if (zend_hash_find(CG(class_table), class_name, len2 + 1, (void **) &ce) != SUCCESS) {
+ zend_error(E_WARNING, "'unserialize_callback_func' (%s) hasn't defined the class it was called for", user_func->value.str.val);
+ incomplete_class = 1;
+ ce = PHP_IC_ENTRY;
+ } else
+ efree(class_name);
+ }
+ }
+ } else
efree(class_name);
-
+
*p = YYCURSOR;
elements = object_common1(UNSERIALIZE_PASSTHRU, ce);
diff --git a/main/main.c b/main/main.c
index 20ee57a25d..2ab207f160 100644
--- a/main/main.c
+++ b/main/main.c
@@ -239,6 +239,7 @@ PHP_INI_BEGIN()
STD_PHP_INI_BOOLEAN("track_errors", "0", PHP_INI_ALL, OnUpdateBool, track_errors, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("y2k_compliance", "0", PHP_INI_ALL, OnUpdateBool, y2k_compliance, php_core_globals, core_globals)
+ STD_PHP_INI_ENTRY("unserialize_callback_func", NULL, PHP_INI_ALL, OnUpdateStringUnempty, unserialize_callback_func, php_core_globals, core_globals)
STD_PHP_INI_ENTRY("arg_separator.output", "&", PHP_INI_ALL, OnUpdateStringUnempty, arg_separator.output, php_core_globals, core_globals)
STD_PHP_INI_ENTRY("arg_separator.input", "&", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateStringUnempty, arg_separator.input, php_core_globals, core_globals)
diff --git a/main/php_globals.h b/main/php_globals.h
index e1caa6eaf3..fdb92900e5 100644
--- a/main/php_globals.h
+++ b/main/php_globals.h
@@ -66,6 +66,8 @@ struct _php_core_globals {
char *output_handler;
+ char *unserialize_callback_func;
+
char *safe_mode_exec_dir;
long memory_limit;
diff --git a/php.ini-dist b/php.ini-dist
index eb78b97005..0f64ff4f39 100644
--- a/php.ini-dist
+++ b/php.ini-dist
@@ -94,6 +94,15 @@ output_buffering = Off
; Setting an output handler automatically turns on output buffering.
output_handler =
+; The unserialize callback function will called (with the undefind class'
+; name as parameter), if the unserializer finds an undefined class
+; which should be instanciated.
+; A warning appears if the specified function is not defined, or if the
+; function doesn't include/implement the missing class.
+; So only set this entry, if you really want to implement such a
+; callback-function.
+unserialize_callback_func=
+
; Transparent output compression using the zlib library
; Valid values for this option are 'off', 'on', or a specific buffer size
; to be used for compression (default is 4KB)