From 55f7303d735995b889f2d39aff60b4ef4e144706 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 2 Nov 2025 16:32:38 +0000 Subject: [PATCH] ext/zip: fix memory leak when encryption is passed as userland array option. Similar issue fixed in GH-19936. close GH-20363 --- NEWS | 5 +++ ext/zip/php_zip.c | 5 +++ ext/zip/tests/oo_addglob_leak.phpt | 51 ++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) create mode 100644 ext/zip/tests/oo_addglob_leak.phpt diff --git a/NEWS b/NEWS index 606f476bb96..d2bc197f0df 100644 --- a/NEWS +++ b/NEWS @@ -95,6 +95,11 @@ PHP NEWS . Fix GH-19722 (_get_osfhandle asserts in debug mode when given a socket). (dktapps) +- Zip: + . Fix memory leak when passing enc_method/enc_password is passed as option + for ZipArchive::addGlob()/addPattern() and with consecutive calls. + (David Carlier) + 23 Oct 2025, PHP 8.3.27 - Core: diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index 552d3a7571d..66f651e46e3 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -1832,6 +1832,11 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* } #ifdef HAVE_ENCRYPTION if (opts.enc_method >= 0) { + if (UNEXPECTED(zip_file_set_encryption(ze_obj->za, ze_obj->last_id, ZIP_EM_NONE, NULL) < 0)) { + zend_array_destroy(Z_ARR_P(return_value)); + php_error_docref(NULL, E_WARNING, "password reset failed"); + RETURN_FALSE; + } if (zip_file_set_encryption(ze_obj->za, ze_obj->last_id, opts.enc_method, opts.enc_password)) { zend_array_destroy(Z_ARR_P(return_value)); RETURN_FALSE; diff --git a/ext/zip/tests/oo_addglob_leak.phpt b/ext/zip/tests/oo_addglob_leak.phpt new file mode 100644 index 00000000000..9040c5565f8 --- /dev/null +++ b/ext/zip/tests/oo_addglob_leak.phpt @@ -0,0 +1,51 @@ +--TEST-- +ZipArchive::addGlob() method leaking after several calls when encryption is set. +--EXTENSIONS-- +zip +--SKIPIF-- + +--FILE-- +open($file, ZipArchive::CREATE | ZipArchive::OVERWRITE)) { + exit('failed'); +} + +$options = [ + 'remove_all_path' => true, + 'comp_method' => ZipArchive::CM_STORE, + 'comp_flags' => 5, + 'enc_method' => ZipArchive::EM_AES_256, + 'enc_password' => 'secret', +]; +var_dump($zip->addGlob($dirname . 'bar.*', GLOB_BRACE, $options)); +var_dump($zip->addGlob($dirname . 'bar.*', GLOB_BRACE, $options)); +?> +--CLEAN-- + +--EXPECTF-- +array(1) { + [0]=> + string(%d) "%s" +} +array(1) { + [0]=> + string(%d) "%s" +}