Commit 201e3cc3d20 for php.net
commit 201e3cc3d20d947ad38ebf6c3fddfee9c957a720
Author: David Carlier <devnexen@gmail.com>
Date: Sun Nov 16 15:47:32 2025 +0000
ext/zip: stricter numeric handling for archive array options.
Use zval_try_get_long() for the numeric entries of the options array
(comp_method, comp_flags, enc_method, flags) so numeric strings are
coerced and non-numeric values raise a TypeError instead of a warning.
remove_all_path is now strictly bool. php_zip_status()/_sys() return
values are widened to zend_long.
close GH-20507
diff --git a/UPGRADING b/UPGRADING
index a6cd3bdef1c..031b6751d85 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -209,6 +209,10 @@ PHP 8.6 UPGRADE NOTES
- Zip:
. ZipArchive::extractTo now raises a TypeError for the files argument if one
or more of the entries is not a string.
+ . ZipArchive::addGlob() and ZipArchive::addPattern() now raise a TypeError
+ when the "remove_all_path" option is not of type bool, or when the
+ "comp_method", "comp_flags", or "enc_method" options are not of type int
+ (numeric strings are coerced), instead of emitting a warning.
- Zlib:
. deflate_init() now raises a TypeError when the value for option "level",
diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c
index 4156a8deb86..1301c6fc6b1 100644
--- a/ext/zip/php_zip.c
+++ b/ext/zip/php_zip.c
@@ -360,6 +360,8 @@ static zend_result php_zip_parse_options(HashTable *options, zip_options *opts)
/* {{{ */
{
zval *option;
+ zend_long tmp;
+ bool failed = false;
/* default values */
opts->flags = ZIP_FL_OVERWRITE;
@@ -370,43 +372,45 @@ static zend_result php_zip_parse_options(HashTable *options, zip_options *opts)
if ((option = zend_hash_str_find(options, "remove_all_path", sizeof("remove_all_path") - 1)) != NULL) {
if (Z_TYPE_P(option) != IS_FALSE && Z_TYPE_P(option) != IS_TRUE) {
- php_error_docref(NULL, E_WARNING, "Option \"remove_all_path\" must be of type bool, %s given",
- zend_zval_value_name(option));
+ zend_type_error("Option \"remove_all_path\" must be of type bool, %s given", zend_zval_value_name(option));
+ return FAILURE;
}
- opts->remove_all_path = zval_get_long(option);
+ opts->remove_all_path = Z_TYPE_P(option) == IS_TRUE;
}
if ((option = zend_hash_str_find(options, "comp_method", sizeof("comp_method") - 1)) != NULL) {
- if (Z_TYPE_P(option) != IS_LONG) {
- php_error_docref(NULL, E_WARNING, "Option \"comp_method\" must be of type int, %s given",
- zend_zval_value_name(option));
+ tmp = zval_try_get_long(option, &failed);
+ if (failed) {
+ zend_type_error("Option \"comp_method\" must be of type int, %s given", zend_zval_value_name(option));
+ return FAILURE;
}
- zend_long comp_method = zval_get_long(option);
+ zend_long comp_method = tmp;
if (comp_method < 0 || comp_method > INT_MAX) {
php_error_docref(NULL, E_WARNING, "Option \"comp_method\" must be between 0 and %d", INT_MAX);
}
opts->comp_method = (zip_int32_t)comp_method;
if ((option = zend_hash_str_find(options, "comp_flags", sizeof("comp_flags") - 1)) != NULL) {
- if (Z_TYPE_P(option) != IS_LONG) {
- php_error_docref(NULL, E_WARNING, "Option \"comp_flags\" must be of type int, %s given",
- zend_zval_value_name(option));
+ tmp = zval_try_get_long(option, &failed);
+ if (failed) {
+ zend_type_error("Option \"comp_flags\" must be of type int, %s given", zend_zval_value_name(option));
+ return FAILURE;
}
- zend_long comp_flags = zval_get_long(option);
- if (comp_flags < 0 || comp_flags > USHRT_MAX) {
+ if (tmp < 0 || tmp > USHRT_MAX) {
php_error_docref(NULL, E_WARNING, "Option \"comp_flags\" must be between 0 and %u", USHRT_MAX);
}
- opts->comp_flags = (zip_uint32_t)comp_flags;
+ opts->comp_flags = (zip_uint32_t)tmp;
}
}
#ifdef HAVE_ENCRYPTION
if ((option = zend_hash_str_find(options, "enc_method", sizeof("enc_method") - 1)) != NULL) {
- if (Z_TYPE_P(option) != IS_LONG) {
- php_error_docref(NULL, E_WARNING, "Option \"enc_method\" must be of type int, %s given",
- zend_zval_value_name(option));
+ tmp = zval_try_get_long(option, &failed);
+ if (failed) {
+ zend_type_error("Option \"enc_method\" must be of type int, %s given", zend_zval_value_name(option));
+ return FAILURE;
}
- opts->enc_method = zval_get_long(option);
+ opts->enc_method = tmp;
if ((option = zend_hash_str_find(options, "enc_password", sizeof("enc_password") - 1)) != NULL) {
if (Z_TYPE_P(option) != IS_STRING) {
@@ -460,12 +464,13 @@ static zend_result php_zip_parse_options(HashTable *options, zip_options *opts)
}
if ((option = zend_hash_str_find(options, "flags", sizeof("flags") - 1)) != NULL) {
- if (Z_TYPE_P(option) != IS_LONG) {
+ tmp = zval_try_get_long(option, &failed);
+ if (failed) {
zend_type_error("Option \"flags\" must be of type int, %s given",
zend_zval_value_name(option));
return FAILURE;
}
- opts->flags = Z_LVAL_P(option);
+ opts->flags = tmp;
}
return SUCCESS;
@@ -515,13 +520,13 @@ static zend_result php_zip_parse_options(HashTable *options, zip_options *opts)
static zend_long php_zip_status(ze_zip_object *obj) /* {{{ */
{
- int zep = obj->err_zip; /* saved err if closed */
+ zend_long zep = (zend_long)obj->err_zip; /* saved err if closed */
if (obj->za) {
zip_error_t *err;
err = zip_get_error(obj->za);
- zep = zip_error_code_zip(err);
+ zep = (zend_long)zip_error_code_zip(err);
zip_error_fini(err);
}
return zep;
@@ -536,13 +541,13 @@ static zend_long php_zip_last_id(ze_zip_object *obj) /* {{{ */
static zend_long php_zip_status_sys(ze_zip_object *obj) /* {{{ */
{
- int syp = obj->err_sys; /* saved err if closed */
+ zend_long syp = (zend_long)obj->err_sys; /* saved err if closed */
if (obj->za) {
zip_error_t *err;
err = zip_get_error(obj->za);
- syp = zip_error_code_system(err);
+ syp = (zend_long)zip_error_code_system(err);
zip_error_fini(err);
}
return syp;