From 3283293b437ecc3fea759e65adeb0936d8e09fdc Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Thu, 9 Apr 2026 12:10:18 -0400 Subject: [PATCH 1/2] Fix GH-21682: ZipArchive is missing the NOT_SERIALIZABLE flag ZipArchive allowed serialization, producing a string that unserializes into an empty object with no open file handle. Add the @not-serializable annotation so serialize() throws an exception. Closes GH-21682 --- ext/zip/php_zip.stub.php | 1 + ext/zip/php_zip_arginfo.h | 4 ++-- ext/zip/tests/gh21682.phpt | 16 ++++++++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 ext/zip/tests/gh21682.phpt diff --git a/ext/zip/php_zip.stub.php b/ext/zip/php_zip.stub.php index 19ea67e07fba..2369934b24f0 100644 --- a/ext/zip/php_zip.stub.php +++ b/ext/zip/php_zip.stub.php @@ -64,6 +64,7 @@ function zip_entry_filesize($zip_entry): int|false {} #[\Deprecated(since: '8.0', message: 'use ZipArchive::statIndex() instead')] function zip_entry_compressionmethod($zip_entry): string|false {} +/** @not-serializable */ class ZipArchive implements Countable { /** diff --git a/ext/zip/php_zip_arginfo.h b/ext/zip/php_zip_arginfo.h index ae2569400efe..4f26a58b6f92 100644 --- a/ext/zip/php_zip_arginfo.h +++ b/ext/zip/php_zip_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit php_zip.stub.php instead. - * Stub hash: bf6706496639628a3287d0026f68f57ecebc4a55 */ + * Stub hash: 3ecdc987268664328008f7d9e2f729f773836bc7 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_open, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0) @@ -530,7 +530,7 @@ static zend_class_entry *register_class_ZipArchive(zend_class_entry *class_entry zend_class_entry ce, *class_entry; INIT_CLASS_ENTRY(ce, "ZipArchive", class_ZipArchive_methods); - class_entry = zend_register_internal_class_with_flags(&ce, NULL, 0); + class_entry = zend_register_internal_class_with_flags(&ce, NULL, ZEND_ACC_NOT_SERIALIZABLE); zend_class_implements(class_entry, 1, class_entry_Countable); zval const_CREATE_value; diff --git a/ext/zip/tests/gh21682.phpt b/ext/zip/tests/gh21682.phpt new file mode 100644 index 000000000000..ed02e305cff4 --- /dev/null +++ b/ext/zip/tests/gh21682.phpt @@ -0,0 +1,16 @@ +--TEST-- +GH-21682 (ZipArchive is missing the NOT_SERIALIZABLE flag) +--EXTENSIONS-- +zip +--FILE-- +getMessage() . "\n"; +} +?> +--EXPECT-- +Serialization of 'ZipArchive' is not allowed From 2d9a1c17dacfd020a47c8ef86dd075fd18f9b3e0 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Fri, 10 Apr 2026 06:47:36 -0400 Subject: [PATCH 2/2] Update bug72434.phpt UAF test and move it to ext/zip/tests bug72434.phpt tested a UAF via unserialize() of ZipArchive. With NOT_SERIALIZABLE, unserialize() rejects the class entirely, preventing the UAF by construction. Update the test to verify the rejection and move it to ext/zip/tests since it requires the zip extension. --- ext/standard/tests/strings/bug72434.phpt | 29 ------------------------ ext/zip/tests/bug72434.phpt | 17 ++++++++++++++ 2 files changed, 17 insertions(+), 29 deletions(-) delete mode 100644 ext/standard/tests/strings/bug72434.phpt create mode 100644 ext/zip/tests/bug72434.phpt diff --git a/ext/standard/tests/strings/bug72434.phpt b/ext/standard/tests/strings/bug72434.phpt deleted file mode 100644 index 6d64baa26fa7..000000000000 --- a/ext/standard/tests/strings/bug72434.phpt +++ /dev/null @@ -1,29 +0,0 @@ ---TEST-- -Bug #72434: ZipArchive class Use After Free Vulnerability in PHP's GC algorithm and unserialize ---FILE-- - rc is 0 -$a = $unserialized_payload[1]; -// Increment the reference counter by 1 again -> rc is 1 -$b = $a; -// Trigger free of $free_me (referenced by $m[1]). -unset($b); -$fill_freed_space_1 = "filler_zval_1"; -$fill_freed_space_2 = "filler_zval_2"; -$fill_freed_space_3 = "filler_zval_3"; -$fill_freed_space_4 = "filler_zval_4"; -debug_zval_dump($unserialized_payload[1]); -?> ---EXPECTF-- -array(1) refcount(3){ - [0]=> - object(stdClass)#%d (0) refcount(1){ - } -} diff --git a/ext/zip/tests/bug72434.phpt b/ext/zip/tests/bug72434.phpt new file mode 100644 index 000000000000..22349bff185d --- /dev/null +++ b/ext/zip/tests/bug72434.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #72434: ZipArchive class Use After Free Vulnerability in PHP's GC algorithm and unserialize +--EXTENSIONS-- +zip +--FILE-- +getMessage() . "\n"; +} +?> +--EXPECT-- +Unserialization of 'ZipArchive' is not allowed