Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
--TEST--
Bad unserialize_callback_func
--FILE--
<?php
ini_set('unserialize_callback_func','PascalCase');

function PascalCase(string $class) {
var_dump($class);
}

try {
unserialize('O:3:"FOO":0:{}');
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
?>
--EXPECTF--
string(3) "FOO"

Warning: unserialize(): Function PascalCase() hasn't defined the class it was called for in %s on line %d
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ try {
}
?>
--EXPECT--
Invalid callback Nonexistent, function "Nonexistent" not found or invalid function name
Unserialization function Nonexistent is not defined
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
--TEST--
unserialize_callback_func which contains null bytes
--FILE--
<?php
ini_set('unserialize_callback_func', "foo\0butno");

function foo(string $name) {
echo "Haha";
}

try {
unserialize('O:3:"FOO":0:{}');
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
?>
--EXPECT--
Unserialization function foo is not defined
22 changes: 11 additions & 11 deletions ext/standard/var_unserializer.re
Original file line number Diff line number Diff line change
Expand Up @@ -1138,8 +1138,6 @@ object ":" uiv ":" ["] {
bool custom_object = 0;
bool has_unserialize = 0;

zval user_func;
zval retval;
zval args[1];

if (!var_hash) return 0;
Expand Down Expand Up @@ -1243,37 +1241,39 @@ object ":" uiv ":" ["] {
}

/* Check for unserialize callback */
if ((PG(unserialize_callback_func) == NULL) || (PG(unserialize_callback_func)[0] == '\0')) {
if ((PG(unserialize_callback_func) == NULL) || (ZSTR_LEN(PG(unserialize_callback_func)) == 0)) {
incomplete_class = 1;
ce = PHP_IC_ENTRY;
break;
}

/* Call unserialize callback */
ZVAL_STRING(&user_func, PG(unserialize_callback_func));
/* Find unserialize callback */
zend_function *callback_fn = zend_hash_find_ptr_lc(EG(function_table), PG(unserialize_callback_func));
if (callback_fn == NULL) {
zend_string_release_ex(class_name, 0);
zend_throw_error(NULL, "Unserialization function %s is not defined", ZSTR_VAL(PG(unserialize_callback_func)));
return 0;
}

/* Call unserialize callback */
ZVAL_STR(&args[0], class_name);
BG(serialize_lock)++;
call_user_function(NULL, NULL, &user_func, &retval, 1, args);
zend_call_known_function(callback_fn, NULL, NULL, NULL, 1, args, NULL);
BG(serialize_lock)--;
zval_ptr_dtor(&retval);

if (EG(exception)) {
zend_string_release_ex(class_name, 0);
zval_ptr_dtor(&user_func);
return 0;
}

/* The callback function may have defined the class */
BG(serialize_lock)++;
if ((ce = zend_lookup_class(class_name)) == NULL) {
php_error_docref(NULL, E_WARNING, "Function %s() hasn't defined the class it was called for", Z_STRVAL(user_func));
php_error_docref(NULL, E_WARNING, "Function %s() hasn't defined the class it was called for", ZSTR_VAL(PG(unserialize_callback_func)));
incomplete_class = 1;
ce = PHP_IC_ENTRY;
}
BG(serialize_lock)--;

zval_ptr_dtor(&user_func);
} while (0);

*p = YYCURSOR;
Expand Down
2 changes: 1 addition & 1 deletion main/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,7 @@ PHP_INI_BEGIN()
STD_PHP_INI_BOOLEAN("auto_globals_jit", "1", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateBool, auto_globals_jit, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("short_open_tag", DEFAULT_SHORT_OPEN_TAG, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, short_tags, zend_compiler_globals, compiler_globals)

STD_PHP_INI_ENTRY("unserialize_callback_func", NULL, PHP_INI_ALL, OnUpdateString, unserialize_callback_func, php_core_globals, core_globals)
STD_PHP_INI_ENTRY("unserialize_callback_func", NULL, PHP_INI_ALL, OnUpdateStr, unserialize_callback_func, php_core_globals, core_globals)
STD_PHP_INI_ENTRY("serialize_precision", "-1", PHP_INI_ALL, OnSetSerializePrecision, serialize_precision, 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)
Expand Down
2 changes: 1 addition & 1 deletion main/php_globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ struct _php_core_globals {

char *output_handler;

char *unserialize_callback_func;
zend_string *unserialize_callback_func;
zend_long serialize_precision;

zend_long memory_limit;
Expand Down