summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-01-02 15:50:44 +0100
committerNikita Popov <nikita.ppv@gmail.com>2020-01-02 15:53:15 +0100
commit8abb2ced399c6869c89783425cfa9483b9ef60cb (patch)
tree1b0d29d94e7483eaac0840d614cb6cec45bc1cda
parent48622970fb10e21d83aaccd15076850d1e1817d3 (diff)
downloadphp-git-8abb2ced399c6869c89783425cfa9483b9ef60cb.tar.gz
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.
-rw-r--r--NEWS2
-rw-r--r--ext/opcache/zend_file_cache.c66
2 files changed, 31 insertions, 37 deletions
diff --git a/NEWS b/NEWS
index bdf508eb43..16d43e66ed 100644
--- a/NEWS
+++ b/NEWS
@@ -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).
diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c
index 36345e63d8..18c69288b3 100644
--- a/ext/opcache/zend_file_cache.c
+++ b/ext/opcache/zend_file_cache.c
@@ -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);
}
}