Skip to content

Commit deb84be

Browse files
committed
BUG #27469 was fixed (serialize() objects of incomplete class)
1 parent 8140003 commit deb84be

File tree

4 files changed

+55
-12
lines changed

4 files changed

+55
-12
lines changed

ext/standard/incomplete_class.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ static void incomplete_class_message(int error_type TSRMLS_DC)
3939
char *class_name = NULL;
4040

4141
if(EG(This)) {
42-
class_name = php_lookup_class_name(EG(This), NULL, 0);
42+
class_name = php_lookup_class_name(EG(This), NULL);
4343
}
4444

4545
if (!class_name)
@@ -114,7 +114,7 @@ zend_class_entry *php_create_incomplete_class(TSRMLS_D)
114114

115115
/* {{{ php_lookup_class_name
116116
*/
117-
char *php_lookup_class_name(zval *object, size_t *nlen, zend_bool del)
117+
char *php_lookup_class_name(zval *object, size_t *nlen)
118118
{
119119
zval **val;
120120
char *retval = NULL;
@@ -128,9 +128,6 @@ char *php_lookup_class_name(zval *object, size_t *nlen, zend_bool del)
128128

129129
if (nlen)
130130
*nlen = Z_STRLEN_PP(val);
131-
132-
if (del)
133-
zend_hash_del(object_properties, MAGIC_MEMBER, sizeof(MAGIC_MEMBER));
134131
}
135132

136133
return (retval);

ext/standard/php_incomplete_class.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@
2929
#define PHP_SET_CLASS_ATTRIBUTES(struc) \
3030
/* OBJECTS_FIXME: Fix for new object model */ \
3131
if (Z_OBJCE_P(struc) == BG(incomplete_class)) { \
32-
class_name = php_lookup_class_name(struc, &name_len, 1); \
32+
class_name = php_lookup_class_name(struc, &name_len); \
3333
free_class_name = 1; \
34+
incomplete_class = 1; \
3435
} else { \
3536
class_name = Z_OBJCE_P(struc)->name; \
3637
name_len = Z_OBJCE_P(struc)->name_length; \
@@ -42,7 +43,8 @@
4243
#define PHP_CLASS_ATTRIBUTES \
4344
char *class_name; \
4445
size_t name_len; \
45-
zend_bool free_class_name = 0 \
46+
zend_bool free_class_name = 0; \
47+
zend_bool incomplete_class = 0
4648

4749
#define INCOMPLETE_CLASS "__PHP_Incomplete_Class"
4850
#define MAGIC_MEMBER "__PHP_Incomplete_Class_Name"
@@ -53,7 +55,7 @@ extern "C" {
5355

5456
zend_class_entry *php_create_incomplete_class(TSRMLS_D);
5557

56-
char *php_lookup_class_name(zval *object, size_t *nlen, zend_bool del);
58+
char *php_lookup_class_name(zval *object, size_t *nlen);
5759
void php_store_class_name(zval *object, const char *name, size_t len);
5860

5961
#ifdef __cplusplus
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
Bug #27469 (serialize() objects of incomplete class)
3+
--FILE--
4+
<?php
5+
$str = 'O:9:"TestClass":0:{}';
6+
$obj = unserialize($str);
7+
var_dump($obj);
8+
echo serialize($obj)."\n";
9+
var_dump($obj);
10+
echo serialize($obj)."\n";
11+
var_dump($obj);
12+
?>
13+
--EXPECT--
14+
object(__PHP_Incomplete_Class)#1 (1) {
15+
["__PHP_Incomplete_Class_Name"]=>
16+
string(9) "TestClass"
17+
}
18+
O:9:"TestClass":0:{}
19+
object(__PHP_Incomplete_Class)#1 (1) {
20+
["__PHP_Incomplete_Class_Name"]=>
21+
string(9) "TestClass"
22+
}
23+
O:9:"TestClass":0:{}
24+
object(__PHP_Incomplete_Class)#1 (1) {
25+
["__PHP_Incomplete_Class_Name"]=>
26+
string(9) "TestClass"
27+
}

ext/standard/var.c

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,7 @@ static inline void php_var_serialize_string(smart_str *buf, char *str, int len)
468468
smart_str_appendl(buf, "\";", 2);
469469
}
470470

471-
static inline void php_var_serialize_class_name(smart_str *buf, zval **struc TSRMLS_DC)
471+
static inline zend_bool php_var_serialize_class_name(smart_str *buf, zval **struc TSRMLS_DC)
472472
{
473473
PHP_CLASS_ATTRIBUTES;
474474

@@ -479,16 +479,21 @@ static inline void php_var_serialize_class_name(smart_str *buf, zval **struc TSR
479479
smart_str_appendl(buf, class_name, name_len);
480480
smart_str_appendl(buf, "\":", 2);
481481
PHP_CLEANUP_CLASS_ATTRIBUTES();
482+
return incomplete_class;
482483
}
483484

484485
static void php_var_serialize_class(smart_str *buf, zval **struc, zval *retval_ptr, HashTable *var_hash TSRMLS_DC)
485486
{
486487
int count;
488+
zend_bool incomplete_class;
487489

488-
php_var_serialize_class_name(buf, struc TSRMLS_CC);
490+
incomplete_class = php_var_serialize_class_name(buf, struc TSRMLS_CC);
489491
/* count after serializing name, since php_var_serialize_class_name
490492
changes the count if the variable is incomplete class */
491493
count = zend_hash_num_elements(HASH_OF(retval_ptr));
494+
if (incomplete_class) {
495+
--count;
496+
}
492497
smart_str_append_long(buf, count);
493498
smart_str_appendl(buf, ":{", 2);
494499

@@ -512,6 +517,9 @@ static void php_var_serialize_class(smart_str *buf, zval **struc, zval *retval_p
512517
if (i == HASH_KEY_NON_EXISTANT)
513518
break;
514519

520+
if (incomplete_class && strcmp(key, MAGIC_MEMBER) == 0) {
521+
continue;
522+
}
515523
zend_hash_get_current_data_ex(HASH_OF(retval_ptr),
516524
(void **) &name, &pos);
517525

@@ -624,17 +632,21 @@ static void php_var_serialize_intern(smart_str *buf, zval **struc, HashTable *va
624632
zval_ptr_dtor(&retval_ptr);
625633
/* fall-through */
626634
}
627-
case IS_ARRAY:
635+
case IS_ARRAY: {
636+
zend_bool incomplete_class = 0;
628637
if (Z_TYPE_PP(struc) == IS_ARRAY) {
629638
smart_str_appendl(buf, "a:", 2);
630639
myht = HASH_OF(*struc);
631640
} else {
632-
php_var_serialize_class_name(buf, struc TSRMLS_CC);
641+
incomplete_class = php_var_serialize_class_name(buf, struc TSRMLS_CC);
633642
myht = Z_OBJPROP_PP(struc);
634643
}
635644
/* count after serializing name, since php_var_serialize_class_name
636645
changes the count if the variable is incomplete class */
637646
i = myht ? zend_hash_num_elements(myht) : 0;
647+
if (i > 0 && incomplete_class) {
648+
--i;
649+
}
638650
smart_str_append_long(buf, i);
639651
smart_str_appendl(buf, ":{", 2);
640652
if (i > 0) {
@@ -651,6 +663,10 @@ static void php_var_serialize_intern(smart_str *buf, zval **struc, HashTable *va
651663
if (i == HASH_KEY_NON_EXISTANT)
652664
break;
653665

666+
if (incomplete_class && strcmp(key, MAGIC_MEMBER) == 0) {
667+
continue;
668+
}
669+
654670
switch (i) {
655671
case HASH_KEY_IS_LONG:
656672
php_var_serialize_long(buf, index);
@@ -674,6 +690,7 @@ static void php_var_serialize_intern(smart_str *buf, zval **struc, HashTable *va
674690
}
675691
smart_str_appendc(buf, '}');
676692
return;
693+
}
677694
default:
678695
smart_str_appendl(buf, "i:0;", 4);
679696
return;

0 commit comments

Comments
 (0)