Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit c9186f7

Browse files
committed
Zend: Implement __unserialize() for Exception/Error
1 parent b46aafa commit c9186f7

File tree

9 files changed

+165
-33
lines changed

9 files changed

+165
-33
lines changed

‎Zend/tests/serialize/bug70121.phpt‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ OK
88
--EXPECTF--
99
Fatal error: Uncaught TypeError: Cannot assign stdClass to property Exception::$previous of type ?Throwable in %s:%d
1010
Stack trace:
11-
#0 %s(%d): unserialize('O:12:"DateInter...')
12-
#1 {main}
11+
#0 [internal function]: Exception->__unserialize(Array)
12+
#1 %s(%d): unserialize('O:12:"DateInter...')
13+
#2 {main}
1314
thrown in %s on line %d

‎Zend/zend_exceptions.c‎

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,95 @@ ZEND_METHOD(Exception, __wakeup)
396396
}
397397
/* }}} */
398398

399+
ZEND_METHOD(Exception, __unserialize)
400+
{
401+
HashTable *ht;
402+
403+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "h", &ht) == FAILURE) {
404+
RETURN_THROWS();
405+
}
406+
407+
/* Fake strict_types as zend_update_property_ex() would coerce values compared to unserialize() */
408+
EG(current_execute_data)->func->common.fn_flags |= ZEND_ACC_STRICT_TYPES;
409+
410+
zend_string *key = NULL;
411+
zval *tmp;
412+
ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, tmp) {
413+
if (UNEXPECTED(key == NULL)) {
414+
zend_throw_error(NULL, "Must have a string key");
415+
RETURN_THROWS();
416+
}
417+
if (ZSTR_VAL(key)[0] == '0円') {
418+
if (zend_string_equals_literal(key, "0円*0円message")) {
419+
if (Z_TYPE_P(tmp) != IS_STRING) {
420+
zend_type_error("Cannot assign %s to property %s::$message of type string",
421+
zend_zval_type_name(tmp), ZSTR_VAL(Z_OBJCE_P(ZEND_THIS)->name));
422+
RETURN_THROWS();
423+
}
424+
zend_update_property_num_checked(NULL, Z_OBJ_P(ZEND_THIS), ZEND_EXCEPTION_MESSAGE_OFF, ZSTR_KNOWN(ZEND_STR_MESSAGE), tmp);
425+
zval_add_ref(tmp);
426+
if (UNEXPECTED(EG(exception))) {
427+
RETURN_THROWS();
428+
}
429+
continue;
430+
}
431+
if (zend_string_equals_literal(key, "0円*0円code")) {
432+
if (Z_TYPE_P(tmp) != IS_LONG) {
433+
zend_type_error("Cannot assign %s to property %s::$code of type int",
434+
zend_zval_type_name(tmp), ZSTR_VAL(Z_OBJCE_P(ZEND_THIS)->name));
435+
RETURN_THROWS();
436+
}
437+
zend_update_property_num_checked(NULL, Z_OBJ_P(ZEND_THIS), ZEND_EXCEPTION_CODE_OFF, ZSTR_KNOWN(ZEND_STR_CODE), tmp);
438+
if (UNEXPECTED(EG(exception))) {
439+
RETURN_THROWS();
440+
}
441+
continue;
442+
}
443+
if (zend_string_equals_literal(key, "0円Exception0円previous") || zend_string_equals_literal(key, "0円Error0円previous")) {
444+
if (Z_TYPE_P(tmp) != IS_NULL && !instanceof_function(Z_OBJCE_P(tmp), zend_ce_throwable)) {
445+
zend_type_error("Cannot assign %s to property %s::$previous of type ?Throwable",
446+
zend_zval_type_name(tmp), ZSTR_VAL(Z_OBJCE_P(ZEND_THIS)->name));
447+
RETURN_THROWS();
448+
}
449+
zend_update_property_num_checked(NULL, Z_OBJ_P(ZEND_THIS), ZEND_EXCEPTION_PREVIOUS_OFF, ZSTR_KNOWN(ZEND_STR_PREVIOUS), tmp);
450+
zval_add_ref(tmp);
451+
if (UNEXPECTED(EG(exception))) {
452+
RETURN_THROWS();
453+
}
454+
continue;
455+
}
456+
if (zend_string_equals_literal(key, "0円Exception0円trace") || zend_string_equals_literal(key, "0円Error0円trace")) {
457+
if (Z_TYPE_P(tmp) != IS_ARRAY) {
458+
zend_type_error("Cannot assign %s to property %s::$trace of type array",
459+
zend_zval_type_name(tmp), ZSTR_VAL(Z_OBJCE_P(ZEND_THIS)->name));
460+
RETURN_THROWS();
461+
}
462+
zend_update_property_num_checked(NULL, Z_OBJ_P(ZEND_THIS), ZEND_EXCEPTION_TRACE_OFF, ZSTR_KNOWN(ZEND_STR_TRACE), tmp);
463+
zval_add_ref(tmp);
464+
if (UNEXPECTED(EG(exception))) {
465+
RETURN_THROWS();
466+
}
467+
continue;
468+
}
469+
if (zend_string_starts_with_cstr(key, ZEND_STRL("0円*0円"))) {
470+
const char *name = ZSTR_VAL(key) + sizeof("0円*0円")-1;
471+
zend_update_property(NULL, Z_OBJ_P(ZEND_THIS), name, strlen(name), tmp);
472+
if (UNEXPECTED(EG(exception))) {
473+
RETURN_THROWS();
474+
}
475+
continue;
476+
}
477+
// TODO: other private props?
478+
} else {
479+
zend_update_property_ex(NULL, Z_OBJ_P(ZEND_THIS), key, tmp);
480+
if (UNEXPECTED(EG(exception))) {
481+
RETURN_THROWS();
482+
}
483+
}
484+
} ZEND_HASH_FOREACH_END();
485+
}
486+
/* }}} */
487+
399488
/* {{{ ErrorException constructor */
400489
ZEND_METHOD(ErrorException, __construct)
401490
{

‎Zend/zend_exceptions.stub.php‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ public function __construct(string $message = "", int $code = 0, ?Throwable $pre
4747
/** @tentative-return-type */
4848
public function __wakeup(): void {}
4949

50+
public function __unserialize(array $data): void {}
51+
5052
final public function getMessage(): string {}
5153

5254
/** @return int */
@@ -111,6 +113,11 @@ public function __construct(string $message = "", int $code = 0, ?Throwable $pre
111113
*/
112114
public function __wakeup(): void {}
113115

116+
/**
117+
* @implementation-alias Exception::__unserialize
118+
*/
119+
public function __unserialize(array $data): void {}
120+
114121
/** @implementation-alias Exception::getMessage */
115122
final public function getMessage(): string {}
116123

‎Zend/zend_exceptions_arginfo.h‎

Lines changed: 10 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎ext/soap/tests/bugs/bug73452.phpt‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ echo unserialize($data);
1313
--EXPECTF--
1414
Fatal error: Uncaught TypeError: Cannot assign %s to property SoapFault::$faultcode of type ?string in %s:%d
1515
Stack trace:
16-
#0 %sbug73452.php(4): unserialize('O:9:"SoapFault"...')
17-
#1 {main}
16+
#0 [internal function]: Exception->__unserialize(Array)
17+
#1 %s(4): unserialize('O:9:"SoapFault"...')
18+
#2 {main}
1819
thrown in %s on line %d

‎ext/standard/tests/serialize/bug69152.phpt‎

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,25 @@
22
Bug #69152: Type Confusion Infoleak Vulnerability in unserialize()
33
--FILE--
44
<?php
5-
$x = unserialize('O:9:"exception":1:{s:16:"'."0円".'Exception'."0円".'trace";s:4:"ryat";}');
6-
echo $x;
7-
$x = unserialize('O:4:"test":1:{s:27:"__PHP_Incomplete_Class_Name";R:1;}');
8-
$x->test();
5+
try {
6+
$x = unserialize('O:9:"exception":1:{s:16:"'."0円".'Exception'."0円".'trace";s:4:"ryat";}');
7+
var_dump($x);
8+
} catch (Throwable $e) {
9+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
10+
}
11+
try {
12+
$x = unserialize('O:4:"test":1:{s:27:"__PHP_Incomplete_Class_Name";R:1;}');
13+
var_dump($x);
14+
$x->test();
15+
} catch (Throwable $e) {
16+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
17+
}
918

1019
?>
11-
--EXPECTF--
12-
Fatal error: Uncaught TypeError: Cannot assign string to property Exception::$trace of type array in %s:%d
13-
Stack trace:
14-
#0 %s(%d): unserialize('O:9:"exception"...')
15-
#1 {main}
16-
thrown in %s on line %d
20+
--EXPECT--
21+
TypeError: Cannot assign string to property Exception::$trace of type array
22+
object(__PHP_Incomplete_Class)#1 (1) {
23+
["__PHP_Incomplete_Class_Name"]=>
24+
*RECURSION*
25+
}
26+
Error: The script tried to call a method on an incomplete object. Please ensure that the class definition "unknown" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide an autoloader to load the class definition

‎ext/standard/tests/serialize/bug69793.phpt‎

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
Bug #69793: Remotely triggerable stack exhaustion via recursive method calls
33
--FILE--
44
<?php
5-
$e = unserialize('O:9:"Exception":7:{s:17:"'."0円".'Exception'."0円".'string";s:1:"a";s:7:"'."0円".'*'."0円".'code";i:0;s:7:"'."0円".'*'."0円".'file";s:0:"";s:7:"'."0円".'*'."0円".'line";i:1337;s:16:"'."0円".'Exception'."0円".'trace";a:0:{}s:19:"'."0円".'Exception'."0円".'previous";i:10;s:10:"'."0円".'*'."0円".'message";N;}');
6-
7-
var_dump($e."");
5+
try {
6+
$e = unserialize('O:9:"Exception":7:{s:17:"'."0円".'Exception'."0円".'string";s:1:"a";s:7:"'."0円".'*'."0円".'code";i:0;s:7:"'."0円".'*'."0円".'file";s:0:"";s:7:"'."0円".'*'."0円".'line";i:1337;s:16:"'."0円".'Exception'."0円".'trace";a:0:{}s:19:"'."0円".'Exception'."0円".'previous";i:10;s:10:"'."0円".'*'."0円".'message";N;}');
7+
var_dump($e);
8+
var_dump($e."");
9+
} catch (Throwable $e) {
10+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
11+
}
812
?>
9-
--EXPECTF--
10-
Fatal error: Uncaught TypeError: Cannot assign int to property Exception::$previous of type ?Throwable in %s:%d
11-
Stack trace:
12-
#0 %s(%d): unserialize('O:9:"Exception"...')
13-
#1 {main}
14-
thrown in %s on line %d
13+
--EXPECT--
14+
TypeError: Cannot assign null to property Exception::$message of type string

‎ext/standard/tests/serialize/bug70963.phpt‎

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,19 @@
22
Bug #70963 (Unserialize shows UNKNOW in result)
33
--FILE--
44
<?php
5-
var_dump(unserialize('a:2:{i:0;O:9:"exception":1:{s:16:"'."0円".'Exception'."0円".'trace";s:4:"test";}i:1;R:3;}'));
6-
var_dump(unserialize('a:2:{i:0;O:9:"exception":1:{s:16:"'."0円".'Exception'."0円".'trace";s:4:"test";}i:1;r:3;}'));
5+
try {
6+
var_dump(unserialize('a:2:{i:0;O:9:"exception":1:{s:16:"'."0円".'Exception'."0円".'trace";s:4:"test";}i:1;R:3;}'));
7+
} catch (Throwable $e) {
8+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
9+
}
10+
try {
11+
var_dump(unserialize('a:2:{i:0;O:9:"exception":1:{s:16:"'."0円".'Exception'."0円".'trace";s:4:"test";}i:1;r:3;}'));
12+
} catch (Throwable $e) {
13+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
14+
}
715
?>
816
--EXPECTF--
9-
Fatal error: Uncaught TypeError: Cannot assign string to property Exception::$trace of type array in %s:%d
10-
Stack trace:
11-
#0 %s(%d): unserialize('a:2:{i:0;O:9:"e...')
12-
#1 {main}
13-
thrown in %s on line %d
17+
TypeError: Cannot assign string to property Exception::$trace of type array
18+
19+
Warning: unserialize(): Error at offset 72 of 73 bytes in %s on line %d
20+
TypeError: Cannot assign string to property Exception::$trace of type array

‎sapi/cli/tests/005.phpt‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ string(183) "Class [ <internal:Core> class stdClass ] {
3737
}
3838

3939
"
40-
string(2232) "Class [ <internal:Core> class Exception implements Stringable, Throwable ] {
40+
string(2406) "Class [ <internal:Core> class Exception implements Stringable, Throwable ] {
4141

4242
- Constants [0] {
4343
}
@@ -58,7 +58,7 @@ string(2232) "Class [ <internal:Core> class Exception implements Stringable, Thr
5858
Property [ private ?Throwable $previous = NULL ]
5959
}
6060

61-
- Methods [11] {
61+
- Methods [12] {
6262
Method [ <internal:Core> private method __clone ] {
6363

6464
- Parameters [0] {
@@ -82,6 +82,14 @@ string(2232) "Class [ <internal:Core> class Exception implements Stringable, Thr
8282
- Tentative return [ void ]
8383
}
8484

85+
Method [ <internal:Core> public method __unserialize ] {
86+
87+
- Parameters [1] {
88+
Parameter #0 [ <required> array $data ]
89+
}
90+
- Return [ void ]
91+
}
92+
8593
Method [ <internal:Core, prototype Throwable> final public method getMessage ] {
8694

8795
- Parameters [0] {

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /