Skip to content

Commit 201e3cc

Browse files
committed
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 phpGH-20507
1 parent c3f1015 commit 201e3cc

2 files changed

Lines changed: 32 additions & 23 deletions

File tree

UPGRADING

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,10 @@ PHP 8.6 UPGRADE NOTES
209209
- Zip:
210210
. ZipArchive::extractTo now raises a TypeError for the files argument if one
211211
or more of the entries is not a string.
212+
. ZipArchive::addGlob() and ZipArchive::addPattern() now raise a TypeError
213+
when the "remove_all_path" option is not of type bool, or when the
214+
"comp_method", "comp_flags", or "enc_method" options are not of type int
215+
(numeric strings are coerced), instead of emitting a warning.
212216

213217
- Zlib:
214218
. deflate_init() now raises a TypeError when the value for option "level",

ext/zip/php_zip.c

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,8 @@ static zend_result php_zip_parse_options(HashTable *options, zip_options *opts)
360360
/* {{{ */
361361
{
362362
zval *option;
363+
zend_long tmp;
364+
bool failed = false;
363365

364366
/* default values */
365367
opts->flags = ZIP_FL_OVERWRITE;
@@ -370,43 +372,45 @@ static zend_result php_zip_parse_options(HashTable *options, zip_options *opts)
370372

371373
if ((option = zend_hash_str_find(options, "remove_all_path", sizeof("remove_all_path") - 1)) != NULL) {
372374
if (Z_TYPE_P(option) != IS_FALSE && Z_TYPE_P(option) != IS_TRUE) {
373-
php_error_docref(NULL, E_WARNING, "Option \"remove_all_path\" must be of type bool, %s given",
374-
zend_zval_value_name(option));
375+
zend_type_error("Option \"remove_all_path\" must be of type bool, %s given", zend_zval_value_name(option));
376+
return FAILURE;
375377
}
376-
opts->remove_all_path = zval_get_long(option);
378+
opts->remove_all_path = Z_TYPE_P(option) == IS_TRUE;
377379
}
378380

379381
if ((option = zend_hash_str_find(options, "comp_method", sizeof("comp_method") - 1)) != NULL) {
380-
if (Z_TYPE_P(option) != IS_LONG) {
381-
php_error_docref(NULL, E_WARNING, "Option \"comp_method\" must be of type int, %s given",
382-
zend_zval_value_name(option));
382+
tmp = zval_try_get_long(option, &failed);
383+
if (failed) {
384+
zend_type_error("Option \"comp_method\" must be of type int, %s given", zend_zval_value_name(option));
385+
return FAILURE;
383386
}
384-
zend_long comp_method = zval_get_long(option);
387+
zend_long comp_method = tmp;
385388
if (comp_method < 0 || comp_method > INT_MAX) {
386389
php_error_docref(NULL, E_WARNING, "Option \"comp_method\" must be between 0 and %d", INT_MAX);
387390
}
388391
opts->comp_method = (zip_int32_t)comp_method;
389392

390393
if ((option = zend_hash_str_find(options, "comp_flags", sizeof("comp_flags") - 1)) != NULL) {
391-
if (Z_TYPE_P(option) != IS_LONG) {
392-
php_error_docref(NULL, E_WARNING, "Option \"comp_flags\" must be of type int, %s given",
393-
zend_zval_value_name(option));
394+
tmp = zval_try_get_long(option, &failed);
395+
if (failed) {
396+
zend_type_error("Option \"comp_flags\" must be of type int, %s given", zend_zval_value_name(option));
397+
return FAILURE;
394398
}
395-
zend_long comp_flags = zval_get_long(option);
396-
if (comp_flags < 0 || comp_flags > USHRT_MAX) {
399+
if (tmp < 0 || tmp > USHRT_MAX) {
397400
php_error_docref(NULL, E_WARNING, "Option \"comp_flags\" must be between 0 and %u", USHRT_MAX);
398401
}
399-
opts->comp_flags = (zip_uint32_t)comp_flags;
402+
opts->comp_flags = (zip_uint32_t)tmp;
400403
}
401404
}
402405

403406
#ifdef HAVE_ENCRYPTION
404407
if ((option = zend_hash_str_find(options, "enc_method", sizeof("enc_method") - 1)) != NULL) {
405-
if (Z_TYPE_P(option) != IS_LONG) {
406-
php_error_docref(NULL, E_WARNING, "Option \"enc_method\" must be of type int, %s given",
407-
zend_zval_value_name(option));
408+
tmp = zval_try_get_long(option, &failed);
409+
if (failed) {
410+
zend_type_error("Option \"enc_method\" must be of type int, %s given", zend_zval_value_name(option));
411+
return FAILURE;
408412
}
409-
opts->enc_method = zval_get_long(option);
413+
opts->enc_method = tmp;
410414

411415
if ((option = zend_hash_str_find(options, "enc_password", sizeof("enc_password") - 1)) != NULL) {
412416
if (Z_TYPE_P(option) != IS_STRING) {
@@ -460,12 +464,13 @@ static zend_result php_zip_parse_options(HashTable *options, zip_options *opts)
460464
}
461465

462466
if ((option = zend_hash_str_find(options, "flags", sizeof("flags") - 1)) != NULL) {
463-
if (Z_TYPE_P(option) != IS_LONG) {
467+
tmp = zval_try_get_long(option, &failed);
468+
if (failed) {
464469
zend_type_error("Option \"flags\" must be of type int, %s given",
465470
zend_zval_value_name(option));
466471
return FAILURE;
467472
}
468-
opts->flags = Z_LVAL_P(option);
473+
opts->flags = tmp;
469474
}
470475

471476
return SUCCESS;
@@ -515,13 +520,13 @@ static zend_result php_zip_parse_options(HashTable *options, zip_options *opts)
515520

516521
static zend_long php_zip_status(ze_zip_object *obj) /* {{{ */
517522
{
518-
int zep = obj->err_zip; /* saved err if closed */
523+
zend_long zep = (zend_long)obj->err_zip; /* saved err if closed */
519524

520525
if (obj->za) {
521526
zip_error_t *err;
522527

523528
err = zip_get_error(obj->za);
524-
zep = zip_error_code_zip(err);
529+
zep = (zend_long)zip_error_code_zip(err);
525530
zip_error_fini(err);
526531
}
527532
return zep;
@@ -536,13 +541,13 @@ static zend_long php_zip_last_id(ze_zip_object *obj) /* {{{ */
536541

537542
static zend_long php_zip_status_sys(ze_zip_object *obj) /* {{{ */
538543
{
539-
int syp = obj->err_sys; /* saved err if closed */
544+
zend_long syp = (zend_long)obj->err_sys; /* saved err if closed */
540545

541546
if (obj->za) {
542547
zip_error_t *err;
543548

544549
err = zip_get_error(obj->za);
545-
syp = zip_error_code_system(err);
550+
syp = (zend_long)zip_error_code_system(err);
546551
zip_error_fini(err);
547552
}
548553
return syp;

0 commit comments

Comments
 (0)