Skip to content

Commit 8abb2ce

Browse files
committed
Fixed bug #79055
Fix file cache serialization of property types. I'm changing the overall type serialization format to perform additional adjustments in order to yield a plausible pointer for zend_type, rather than using an entirely separate serialization format, as was previously done. That would have been annoying to extend to the case of CE pointers.
1 parent 4862297 commit 8abb2ce

File tree

2 files changed

+31
-37
lines changed

2 files changed

+31
-37
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ PHP NEWS
3838
. Fixed bug #78986 (Opcache segfaults when inheriting ctor from immutable
3939
into mutable class). (Nikita)
4040
. Fixed bug #79040 (Warning Opcode handlers are unusable due to ASLR). (cmb)
41+
. Fixed bug #79055 (Typed property become unknown with OPcache file cache).
42+
(Nikita)
4143

4244
- Pcntl:
4345
. Fixed bug #78402 (Converting null to string in error message is bad DX).

ext/opcache/zend_file_cache.c

Lines changed: 29 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -371,18 +371,26 @@ static void zend_file_cache_serialize_zval(zval *zv,
371371
}
372372
}
373373

374+
/* Adjust serialized pointer to conform to zend_type assumptions:
375+
* Pointer must have low two bits unset and be larger than 0x400. */
376+
#define ZEND_TYPE_PTR_ENCODE(ptr) \
377+
(void*)(((uintptr_t)ptr << 2) + 0x400)
378+
#define ZEND_TYPE_PTR_DECODE(ptr) \
379+
(void*)(((uintptr_t)ptr - 0x400) >> 2)
380+
374381
static void zend_file_cache_serialize_type(
375382
zend_type *type, zend_persistent_script *script, zend_file_cache_metainfo *info, void *buf)
376383
{
377-
if (ZEND_TYPE_IS_CLASS(*type)) {
378-
zend_bool allow_null = ZEND_TYPE_ALLOW_NULL(*type);
379-
zend_string *type_name = ZEND_TYPE_NAME(*type);
380-
381-
SERIALIZE_STR(type_name);
382-
*type =
383-
(Z_UL(1) << (sizeof(zend_type)*8-1)) | /* type is class */
384-
(allow_null ? (Z_UL(1) << (sizeof(zend_type)*8-2)) : Z_UL(0)) | /* type allow null */
385-
(zend_type)type_name;
384+
if (ZEND_TYPE_IS_NAME(*type)) {
385+
zend_string *name = ZEND_TYPE_NAME(*type);
386+
SERIALIZE_STR(name);
387+
name = ZEND_TYPE_PTR_ENCODE(name);
388+
*type = ZEND_TYPE_ENCODE_CLASS(name, ZEND_TYPE_ALLOW_NULL(*type));
389+
} else if (ZEND_TYPE_IS_CE(*type)) {
390+
zend_class_entry *ce = ZEND_TYPE_CE(*type);
391+
SERIALIZE_PTR(ce);
392+
ce = ZEND_TYPE_PTR_ENCODE(ce);
393+
*type = ZEND_TYPE_ENCODE_CE(ce, ZEND_TYPE_ALLOW_NULL(*type));
386394
}
387395
}
388396

@@ -583,17 +591,7 @@ static void zend_file_cache_serialize_prop_info(zval *zv,
583591
SERIALIZE_STR(prop->doc_comment);
584592
}
585593
}
586-
if (prop->type) {
587-
if (ZEND_TYPE_IS_NAME(prop->type)) {
588-
zend_string *name = ZEND_TYPE_NAME(prop->type);
589-
SERIALIZE_STR(name);
590-
prop->type = ZEND_TYPE_ENCODE_CLASS(name, ZEND_TYPE_ALLOW_NULL(prop->type));
591-
} else if (ZEND_TYPE_IS_CE(prop->type)) {
592-
zend_class_entry *ce = ZEND_TYPE_CE(prop->type);
593-
SERIALIZE_PTR(ce);
594-
prop->type = ZEND_TYPE_ENCODE_CE(ce, ZEND_TYPE_ALLOW_NULL(prop->type));
595-
}
596-
}
594+
zend_file_cache_serialize_type(&prop->type, script, info, buf);
597595
}
598596
}
599597

@@ -1089,12 +1087,16 @@ static void zend_file_cache_unserialize_zval(zval *zv,
10891087
static void zend_file_cache_unserialize_type(
10901088
zend_type *type, zend_persistent_script *script, void *buf)
10911089
{
1092-
if (*type & (Z_UL(1) << (sizeof(zend_type)*8-1))) { /* type is class */
1093-
zend_bool allow_null = (*type & (Z_UL(1) << (sizeof(zend_type)*8-2))) != 0; /* type allow null */
1094-
zend_string *type_name = (zend_string*)(*type & ~(((Z_UL(1) << (sizeof(zend_type)*8-1))) | ((Z_UL(1) << (sizeof(zend_type)*8-2)))));
1095-
1096-
UNSERIALIZE_STR(type_name);
1097-
*type = ZEND_TYPE_ENCODE_CLASS(type_name, allow_null);
1090+
if (ZEND_TYPE_IS_NAME(*type)) {
1091+
zend_string *name = ZEND_TYPE_NAME(*type);
1092+
name = ZEND_TYPE_PTR_DECODE(name);
1093+
UNSERIALIZE_STR(name);
1094+
*type = ZEND_TYPE_ENCODE_CLASS(name, ZEND_TYPE_ALLOW_NULL(*type));
1095+
} else if (ZEND_TYPE_IS_CE(*type)) {
1096+
zend_class_entry *ce = ZEND_TYPE_CE(*type);
1097+
ce = ZEND_TYPE_PTR_DECODE(ce);
1098+
UNSERIALIZE_PTR(ce);
1099+
*type = ZEND_TYPE_ENCODE_CE(ce, ZEND_TYPE_ALLOW_NULL(*type));
10981100
}
10991101
}
11001102

@@ -1291,17 +1293,7 @@ static void zend_file_cache_unserialize_prop_info(zval *zv,
12911293
UNSERIALIZE_STR(prop->doc_comment);
12921294
}
12931295
}
1294-
if (prop->type) {
1295-
if (ZEND_TYPE_IS_NAME(prop->type)) {
1296-
zend_string *name = ZEND_TYPE_NAME(prop->type);
1297-
UNSERIALIZE_STR(name);
1298-
prop->type = ZEND_TYPE_ENCODE_CLASS(name, ZEND_TYPE_ALLOW_NULL(prop->type));
1299-
} else if (ZEND_TYPE_IS_CE(prop->type)) {
1300-
zend_class_entry *ce = ZEND_TYPE_CE(prop->type);
1301-
UNSERIALIZE_PTR(ce);
1302-
prop->type = ZEND_TYPE_ENCODE_CE(ce, ZEND_TYPE_ALLOW_NULL(prop->type));
1303-
}
1304-
}
1296+
zend_file_cache_unserialize_type(&prop->type, script, buf);
13051297
}
13061298
}
13071299

0 commit comments

Comments
 (0)