diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index 9fc0af4fcaca4..e9b560ab1df61 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -1261,6 +1261,7 @@ PHP_FUNCTION(zip_read) RETURN_FALSE; } + zr_rsrc->zip_rsrc_handle = Z_RES_P(zip_dp)->handle; zr_rsrc->zf = zip_fopen_index(rsrc_int->za, rsrc_int->index_current, 0); if (zr_rsrc->zf) { rsrc_int->index_current++; @@ -1377,7 +1378,7 @@ static void php_zip_entry_get_info(INTERNAL_FUNCTION_PARAMETERS, int opt) /* {{{ RETURN_THROWS(); } - if (!zr_rsrc->zf) { + if (!zr_rsrc->zf || !zend_hash_index_exists(&EG(regular_list), zr_rsrc->zip_rsrc_handle)) { RETURN_FALSE; } diff --git a/ext/zip/php_zip.h b/ext/zip/php_zip.h index 82f7b5e057a43..4f4750993f990 100644 --- a/ext/zip/php_zip.h +++ b/ext/zip/php_zip.h @@ -60,6 +60,9 @@ typedef zip_rsrc * zip_rsrc_ptr; typedef struct _ze_zip_read_rsrc { struct zip_file *zf; struct zip_stat sb; + /* Used to check if the zip resource still exists, + * without holding a reference. This works because the IDs are unique. */ + zend_long zip_rsrc_handle; } zip_read_rsrc; /* Extends zend object */ diff --git a/ext/zip/tests/gh17319.phpt b/ext/zip/tests/gh17319.phpt new file mode 100644 index 0000000000000..3f41be287c637 --- /dev/null +++ b/ext/zip/tests/gh17319.phpt @@ -0,0 +1,19 @@ +--TEST-- +GH-17139 - zip_entry_name() crash +--EXTENSIONS-- +zip +--FILE-- + +--EXPECTF-- +Deprecated: Function zip_open() is deprecated since 8.0, use ZipArchive::open() instead in %s on line %d + +Deprecated: Function zip_read() is deprecated since 8.0, use ZipArchive::statIndex() instead in %s on line %d + +Deprecated: Function zip_entry_name() is deprecated since 8.0, use ZipArchive::statIndex() instead in %s on line %d +bool(false)