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.
This commit is contained in:
Nikita Popov 2020-01-02 15:50:44 +01:00
parent 48622970fb
commit 8abb2ced39
2 changed files with 31 additions and 37 deletions

2
NEWS
View File

@ -38,6 +38,8 @@ PHP NEWS
. Fixed bug #78986 (Opcache segfaults when inheriting ctor from immutable
into mutable class). (Nikita)
. Fixed bug #79040 (Warning Opcode handlers are unusable due to ASLR). (cmb)
. Fixed bug #79055 (Typed property become unknown with OPcache file cache).
(Nikita)
- Pcntl:
. Fixed bug #78402 (Converting null to string in error message is bad DX).

View File

@ -371,18 +371,26 @@ static void zend_file_cache_serialize_zval(zval *zv,
}
}
/* Adjust serialized pointer to conform to zend_type assumptions:
* Pointer must have low two bits unset and be larger than 0x400. */
#define ZEND_TYPE_PTR_ENCODE(ptr) \
(void*)(((uintptr_t)ptr << 2) + 0x400)
#define ZEND_TYPE_PTR_DECODE(ptr) \
(void*)(((uintptr_t)ptr - 0x400) >> 2)
static void zend_file_cache_serialize_type(
zend_type *type, zend_persistent_script *script, zend_file_cache_metainfo *info, void *buf)
{
if (ZEND_TYPE_IS_CLASS(*type)) {
zend_bool allow_null = ZEND_TYPE_ALLOW_NULL(*type);
zend_string *type_name = ZEND_TYPE_NAME(*type);
SERIALIZE_STR(type_name);
*type =
(Z_UL(1) << (sizeof(zend_type)*8-1)) | /* type is class */
(allow_null ? (Z_UL(1) << (sizeof(zend_type)*8-2)) : Z_UL(0)) | /* type allow null */
(zend_type)type_name;
if (ZEND_TYPE_IS_NAME(*type)) {
zend_string *name = ZEND_TYPE_NAME(*type);
SERIALIZE_STR(name);
name = ZEND_TYPE_PTR_ENCODE(name);
*type = ZEND_TYPE_ENCODE_CLASS(name, ZEND_TYPE_ALLOW_NULL(*type));
} else if (ZEND_TYPE_IS_CE(*type)) {
zend_class_entry *ce = ZEND_TYPE_CE(*type);
SERIALIZE_PTR(ce);
ce = ZEND_TYPE_PTR_ENCODE(ce);
*type = ZEND_TYPE_ENCODE_CE(ce, ZEND_TYPE_ALLOW_NULL(*type));
}
}
@ -583,17 +591,7 @@ static void zend_file_cache_serialize_prop_info(zval *zv,
SERIALIZE_STR(prop->doc_comment);
}
}
if (prop->type) {
if (ZEND_TYPE_IS_NAME(prop->type)) {
zend_string *name = ZEND_TYPE_NAME(prop->type);
SERIALIZE_STR(name);
prop->type = ZEND_TYPE_ENCODE_CLASS(name, ZEND_TYPE_ALLOW_NULL(prop->type));
} else if (ZEND_TYPE_IS_CE(prop->type)) {
zend_class_entry *ce = ZEND_TYPE_CE(prop->type);
SERIALIZE_PTR(ce);
prop->type = ZEND_TYPE_ENCODE_CE(ce, ZEND_TYPE_ALLOW_NULL(prop->type));
}
}
zend_file_cache_serialize_type(&prop->type, script, info, buf);
}
}
@ -1089,12 +1087,16 @@ static void zend_file_cache_unserialize_zval(zval *zv,
static void zend_file_cache_unserialize_type(
zend_type *type, zend_persistent_script *script, void *buf)
{
if (*type & (Z_UL(1) << (sizeof(zend_type)*8-1))) { /* type is class */
zend_bool allow_null = (*type & (Z_UL(1) << (sizeof(zend_type)*8-2))) != 0; /* type allow null */
zend_string *type_name = (zend_string*)(*type & ~(((Z_UL(1) << (sizeof(zend_type)*8-1))) | ((Z_UL(1) << (sizeof(zend_type)*8-2)))));
UNSERIALIZE_STR(type_name);
*type = ZEND_TYPE_ENCODE_CLASS(type_name, allow_null);
if (ZEND_TYPE_IS_NAME(*type)) {
zend_string *name = ZEND_TYPE_NAME(*type);
name = ZEND_TYPE_PTR_DECODE(name);
UNSERIALIZE_STR(name);
*type = ZEND_TYPE_ENCODE_CLASS(name, ZEND_TYPE_ALLOW_NULL(*type));
} else if (ZEND_TYPE_IS_CE(*type)) {
zend_class_entry *ce = ZEND_TYPE_CE(*type);
ce = ZEND_TYPE_PTR_DECODE(ce);
UNSERIALIZE_PTR(ce);
*type = ZEND_TYPE_ENCODE_CE(ce, ZEND_TYPE_ALLOW_NULL(*type));
}
}
@ -1291,17 +1293,7 @@ static void zend_file_cache_unserialize_prop_info(zval *zv,
UNSERIALIZE_STR(prop->doc_comment);
}
}
if (prop->type) {
if (ZEND_TYPE_IS_NAME(prop->type)) {
zend_string *name = ZEND_TYPE_NAME(prop->type);
UNSERIALIZE_STR(name);
prop->type = ZEND_TYPE_ENCODE_CLASS(name, ZEND_TYPE_ALLOW_NULL(prop->type));
} else if (ZEND_TYPE_IS_CE(prop->type)) {
zend_class_entry *ce = ZEND_TYPE_CE(prop->type);
UNSERIALIZE_PTR(ce);
prop->type = ZEND_TYPE_ENCODE_CE(ce, ZEND_TYPE_ALLOW_NULL(prop->type));
}
}
zend_file_cache_unserialize_type(&prop->type, script, buf);
}
}