From de7ba3e7377ebb10c26e1ccecece29fe84503721 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 18 Aug 2021 10:55:17 +0200 Subject: [PATCH] Fix repeated file cache unserialization of zval string The IS_UNSERIALIZED check here does not work if the string is interned (serialized with file_cache_only=0) but unserialization happens with file_cache_only=1. In this case the unserializde string will be in the str area after mem, which is not included in the script size, and which is also not accessible at this point without threading through more information. Work around the problem by checking for the serialized representation instead. --- ext/opcache/zend_file_cache.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index 62a2d261ff2..1f1677ddf2b 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -1140,7 +1140,9 @@ static void zend_file_cache_unserialize_zval(zval *zv, { switch (Z_TYPE_P(zv)) { case IS_STRING: - if (!IS_UNSERIALIZED(Z_STR_P(zv))) { + /* We can't use !IS_UNSERIALIZED here, because that does not recognize unserialized + * interned strings in non-shm mode. */ + if (IS_SERIALIZED(Z_STR_P(zv)) || IS_SERIALIZED_INTERNED(Z_STR_P(zv))) { UNSERIALIZE_STR(Z_STR_P(zv)); } break;