Skip to content

Commit 2488e8e

Browse files
Address Arnaud's comments
1 parent 6a8cde7 commit 2488e8e

File tree

2 files changed

+53
-16
lines changed

2 files changed

+53
-16
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ PHP NEWS
5454
(Girgias)
5555
. Fixed bug GH-19801 (leaks in var_dump() and debug_zval_dump()).
5656
(alexandre-daubois)
57+
. Fixed GH-14402 (SplPriorityQueue, SplMinHeap, and SplMaxHeap lost their
58+
data on serialize()). (alexandre-daubois)
5759

5860
- URI:
5961
. Fixed bug GH-19780 (InvalidUrlException should check $errors argument).

ext/spl/spl_heap.c

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,9 +1077,14 @@ static void spl_heap_serialize_internal_state(zval *return_value, spl_heap_objec
10771077

10781078
array_init(return_value);
10791079
add_assoc_long(return_value, "flags", intern->flags);
1080-
1080+
10811081
array_init_size(&heap_elements, heap_count);
10821082

1083+
if (heap_count == 0) {
1084+
add_assoc_zval(return_value, "heap_elements", &heap_elements);
1085+
return;
1086+
}
1087+
10831088
for (int heap_idx = 0; heap_idx < heap_count; ++heap_idx) {
10841089
if (is_pqueue) {
10851090
spl_pqueue_elem *elem = spl_heap_elem(intern->heap, heap_idx);
@@ -1100,62 +1105,66 @@ static void spl_heap_serialize_internal_state(zval *return_value, spl_heap_objec
11001105
add_assoc_zval(return_value, "heap_elements", &heap_elements);
11011106
}
11021107

1103-
static void spl_heap_unserialize_internal_state(HashTable *state_ht, spl_heap_object *intern, zval *this_ptr, bool is_pqueue)
1108+
static zend_result spl_heap_unserialize_internal_state(HashTable *state_ht, spl_heap_object *intern, zval *this_ptr, bool is_pqueue)
11041109
{
11051110
zval *flags_val = zend_hash_str_find(state_ht, "flags", strlen("flags"));
11061111
if (!flags_val || Z_TYPE_P(flags_val) != IS_LONG) {
1107-
zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(intern->std.ce->name));
1108-
return;
1112+
return FAILURE;
11091113
}
11101114

11111115
zend_long flags_value = Z_LVAL_P(flags_val);
11121116

11131117
if (is_pqueue) {
11141118
flags_value &= SPL_PQUEUE_EXTR_MASK;
11151119
if (!flags_value) {
1116-
zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(intern->std.ce->name));
1117-
return;
1120+
return FAILURE;
11181121
}
1122+
} else if (flags_value != 0) { /* Regular heaps should not have user-visible flags */
1123+
return FAILURE;
11191124
}
11201125

11211126
intern->flags = (int) flags_value;
11221127

11231128
zval *heap_elements = zend_hash_str_find(state_ht, "heap_elements", strlen("heap_elements"));
11241129
if (!heap_elements) {
1125-
zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(intern->std.ce->name));
1126-
return;
1130+
return FAILURE;
11271131
}
11281132

11291133
if (Z_TYPE_P(heap_elements) != IS_ARRAY) {
1130-
zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(intern->std.ce->name));
1131-
return;
1134+
return FAILURE;
11321135
}
11331136

11341137
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(heap_elements), zval *val) {
11351138
if (is_pqueue) {
11361139
/* PriorityQueue elements are serialized as arrays with 'data' and 'priority' keys */
11371140
if (Z_TYPE_P(val) != IS_ARRAY || zend_hash_num_elements(Z_ARRVAL_P(val)) != 2) {
1138-
zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(intern->std.ce->name));
1139-
return;
1141+
return FAILURE;
11401142
}
11411143

11421144
zval *data_val = zend_hash_str_find(Z_ARRVAL_P(val), "data", strlen("data") );
11431145
zval *priority_val = zend_hash_str_find(Z_ARRVAL_P(val), "priority", strlen("priority"));
11441146

11451147
if (!data_val || !priority_val) {
1146-
zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(intern->std.ce->name));
1147-
return;
1148+
return FAILURE;
11481149
}
11491150

11501151
spl_pqueue_elem elem;
11511152
ZVAL_COPY(&elem.data, data_val);
11521153
ZVAL_COPY(&elem.priority, priority_val);
11531154
spl_ptr_heap_insert(intern->heap, &elem, this_ptr);
1155+
if (EG(exception)) {
1156+
return FAILURE;
1157+
}
11541158
} else {
11551159
Z_TRY_ADDREF_P(val);
11561160
spl_ptr_heap_insert(intern->heap, val, this_ptr);
1161+
if (EG(exception)) {
1162+
return FAILURE;
1163+
}
11571164
}
11581165
} ZEND_HASH_FOREACH_END();
1166+
1167+
return SUCCESS;
11591168
}
11601169

11611170
PHP_METHOD(SplPriorityQueue, __serialize)
@@ -1169,6 +1178,11 @@ PHP_METHOD(SplPriorityQueue, __serialize)
11691178
RETURN_THROWS();
11701179
}
11711180

1181+
if (intern->heap->flags & SPL_HEAP_WRITE_LOCKED) {
1182+
zend_throw_exception(spl_ce_RuntimeException, "Cannot serialize heap while it is being modified.", 0);
1183+
RETURN_THROWS();
1184+
}
1185+
11721186
array_init(return_value);
11731187

11741188
ZVAL_ARR(&props, zend_std_get_properties(&intern->std));
@@ -1211,10 +1225,18 @@ PHP_METHOD(SplPriorityQueue, __unserialize)
12111225
RETURN_THROWS();
12121226
}
12131227

1214-
spl_heap_unserialize_internal_state(Z_ARRVAL_P(state), intern, ZEND_THIS, true);
1228+
if (spl_heap_unserialize_internal_state(Z_ARRVAL_P(state), intern, ZEND_THIS, true) != SUCCESS) {
1229+
zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(intern->std.ce->name));
1230+
RETURN_THROWS();
1231+
}
1232+
12151233
if (EG(exception)) {
12161234
RETURN_THROWS();
12171235
}
1236+
1237+
if (UNEXPECTED(spl_heap_consistency_validations(intern, false) != SUCCESS)) {
1238+
RETURN_THROWS();
1239+
}
12181240
}
12191241

12201242
PHP_METHOD(SplHeap, __serialize)
@@ -1228,6 +1250,11 @@ PHP_METHOD(SplHeap, __serialize)
12281250
RETURN_THROWS();
12291251
}
12301252

1253+
if (intern->heap->flags & SPL_HEAP_WRITE_LOCKED) {
1254+
zend_throw_exception(spl_ce_RuntimeException, "Cannot serialize heap while it is being modified.", 0);
1255+
RETURN_THROWS();
1256+
}
1257+
12311258
array_init(return_value);
12321259

12331260
ZVAL_ARR(&props, zend_std_get_properties(&intern->std));
@@ -1270,10 +1297,18 @@ PHP_METHOD(SplHeap, __unserialize)
12701297
RETURN_THROWS();
12711298
}
12721299

1273-
spl_heap_unserialize_internal_state(Z_ARRVAL_P(state), intern, ZEND_THIS, false);
1300+
if (spl_heap_unserialize_internal_state(Z_ARRVAL_P(state), intern, ZEND_THIS, false) != SUCCESS) {
1301+
zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(intern->std.ce->name));
1302+
RETURN_THROWS();
1303+
}
1304+
12741305
if (EG(exception)) {
12751306
RETURN_THROWS();
12761307
}
1308+
1309+
if (UNEXPECTED(spl_heap_consistency_validations(intern, false) != SUCCESS)) {
1310+
RETURN_THROWS();
1311+
}
12771312
}
12781313

12791314
/* iterator handler table */

0 commit comments

Comments
 (0)