[php-src] master: zlib: deprecate passing objects as array

Gina Peter Banyard <[email protected]>
Newsgroups gmane.comp.php.cvs.general
Message-ID <[email protected]>
Author: Gina Peter Banyard (Girgias)
Date: 2026-08-10T18:21:19+01:00

Commit: https://github.com/php/php-src/commit/f8c854e82faec850981a4a65e6c64a822ec580af
Raw diff: https://github.com/php/php-src/commit/f8c854e82faec850981a4a65e6c64a822ec580af.diff

zlib: deprecate passing objects as array

Implements RFCs:
- https://wiki.php.net/rfc/deprecations_php_8_6#passing_objects_for_options_parameter_of_deflate_init_and_inflate_init
- https://wiki.php.net/rfc/deprecations_php_8_6#passing_objects_as_parameters_to_the_zlibinflate_and_zlibdeflate_stream_filters

Changed paths:
  A  ext/zlib/tests/gh17745_inflate.phpt
  A  ext/zlib/tests/gh22142_inflate.phpt
  M  ext/zlib/tests/filter_broken_object_options.phpt
  M  ext/zlib/tests/gh17745.phpt
  M  ext/zlib/tests/gh22142.phpt
  M  ext/zlib/zlib.c
  M  ext/zlib/zlib_filter.c


Diff:

diff --git a/ext/zlib/tests/filter_broken_object_options.phpt b/ext/zlib/tests/filter_broken_object_options.phpt
index beb0fef9fb13..a43c85f36718 100644
--- a/ext/zlib/tests/filter_broken_object_options.phpt
+++ b/ext/zlib/tests/filter_broken_object_options.phpt
@@ -17,5 +17,8 @@ stream_filter_append($fp, 'zlib.inflate', STREAM_FILTER_WRITE, new Params);
 fwrite($fp, "Hello world, hopefully not broken\n");
 
 ?>
---EXPECT--
+--EXPECTF--
+Deprecated: stream_filter_append(): Passing an object for filter parameters for zlib.deflate is deprecated, call get_object_vars() first instead in %s on line %d
+
+Deprecated: stream_filter_append(): Passing an object for filter parameters for zlib.inflate is deprecated, call get_object_vars() first instead in %s on line %d
 Hello world, hopefully not broken
diff --git a/ext/zlib/tests/gh17745.phpt b/ext/zlib/tests/gh17745.phpt
index 64331269dcda..5e522ee96145 100644
--- a/ext/zlib/tests/gh17745.phpt
+++ b/ext/zlib/tests/gh17745.phpt
@@ -13,8 +13,11 @@ class Options {
 }
 var_dump(deflate_init(ZLIB_ENCODING_RAW, new Options));
 ?>
---EXPECT--
+--EXPECTF--
+Deprecated: deflate_init(): Passing an object for argument #2 $option to deflate_init() is deprecated, call get_object_vars() first instead in %s on line %d
 object(DeflateContext)#2 (0) {
 }
+
+Deprecated: deflate_init(): Passing an object for argument #2 $option to deflate_init() is deprecated, call get_object_vars() first instead in %s on line %d
 object(DeflateContext)#3 (0) {
 }
diff --git a/ext/zlib/tests/gh17745_inflate.phpt b/ext/zlib/tests/gh17745_inflate.phpt
new file mode 100644
index 000000000000..c87f0fbea9dd
--- /dev/null
+++ b/ext/zlib/tests/gh17745_inflate.phpt
@@ -0,0 +1,23 @@
+--TEST--
+GH-17745 (zlib extension incorrectly handles object arguments)
+--EXTENSIONS--
+zlib
+--FILE--
+<?php
+$obj = new stdClass;
+$obj->level = 3;
+var_dump(inflate_init(ZLIB_ENCODING_RAW, $obj));
+
+class Options {
+    public int $level = 3;
+}
+var_dump(inflate_init(ZLIB_ENCODING_RAW, new Options));
+?>
+--EXPECTF--
+Deprecated: inflate_init(): Passing an object for argument #2 $option to inflate_init() is deprecated, call get_object_vars() first instead in %s on line %d
+object(InflateContext)#2 (0) {
+}
+
+Deprecated: inflate_init(): Passing an object for argument #2 $option to inflate_init() is deprecated, call get_object_vars() first instead in %s on line %d
+object(InflateContext)#3 (0) {
+}
diff --git a/ext/zlib/tests/gh22142.phpt b/ext/zlib/tests/gh22142.phpt
index 9bbb9332df30..481ffef342aa 100644
--- a/ext/zlib/tests/gh22142.phpt
+++ b/ext/zlib/tests/gh22142.phpt
@@ -16,5 +16,6 @@ try {
 }
 
 ?>
---EXPECT--
+--EXPECTF--
+Deprecated: deflate_init(): Passing an object for argument #2 $option to deflate_init() is deprecated, call get_object_vars() first instead in %s on line %d
 TypeError: deflate_init(): Argument #2 ($options) the value for option "level" must be of type int, null given
diff --git a/ext/zlib/tests/gh22142_inflate.phpt b/ext/zlib/tests/gh22142_inflate.phpt
new file mode 100644
index 000000000000..853099e4911d
--- /dev/null
+++ b/ext/zlib/tests/gh22142_inflate.phpt
@@ -0,0 +1,21 @@
+--TEST--
+GH-22142 (Assertion failure in zendi_try_get_long() on IS_UNDEF)
+--EXTENSIONS--
+zlib
+--FILE--
+<?php
+
+class Options {
+    public int $window;
+}
+
+try {
+    inflate_init(ZLIB_ENCODING_DEFLATE, new Options());
+} catch (TypeError $e) {
+    echo $e::class, ': ', $e->getMessage(), PHP_EOL;
+}
+
+?>
+--EXPECTF--
+Deprecated: inflate_init(): Passing an object for argument #2 $option to inflate_init() is deprecated, call get_object_vars() first instead in %s on line %d
+TypeError: inflate_init(): Argument #2 ($options) the value for option "window" must be of type int, null given
diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c
index 5b630d74c889..44ab23233ac8 100644
--- a/ext/zlib/zlib.c
+++ b/ext/zlib/zlib.c
@@ -881,12 +881,24 @@ PHP_FUNCTION(inflate_init)
 	zend_long encoding, window = 15;
 	char *dict = NULL;
 	size_t dictlen = 0;
+	zval *options_zv = NULL;
 	HashTable *options = (HashTable *) &zend_empty_array;
 
-	if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "l|H", &encoding, &options)) {
+	if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "l|A", &encoding, &options_zv)) {
 		RETURN_THROWS();
 	}
 
+	if (options_zv) {
+		if (Z_TYPE_P(options_zv) == IS_OBJECT) {
+			php_error_docref(NULL, E_DEPRECATED,
+				"Passing an object for argument #2 $option to inflate_init() is deprecated, call get_object_vars() first instead");
+			if (UNEXPECTED(EG(exception))) {
+				RETURN_THROWS();
+			}
+		}
+		options = HASH_OF(options_zv);
+	}
+
 	if (!zlib_get_long_option(options, ZEND_STRL("window"), &window)) {
 		RETURN_THROWS();
 	}
@@ -1100,12 +1112,24 @@ PHP_FUNCTION(deflate_init)
 	zend_long encoding, level = -1, memory = 8, window = 15, strategy = Z_DEFAULT_STRATEGY;
 	char *dict = NULL;
 	size_t dictlen = 0;
+	zval *options_zv = NULL;
 	HashTable *options = (HashTable*)&zend_empty_array;
 
-	if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "l|H", &encoding, &options)) {
+	if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "l|A", &encoding, &options_zv)) {
 		RETURN_THROWS();
 	}
 
+	if (options_zv) {
+		if (Z_TYPE_P(options_zv) == IS_OBJECT) {
+			php_error_docref(NULL, E_DEPRECATED,
+				"Passing an object for argument #2 $option to deflate_init() is deprecated, call get_object_vars() first instead");
+			if (UNEXPECTED(EG(exception))) {
+				RETURN_THROWS();
+			}
+		}
+		options = HASH_OF(options_zv);
+	}
+
 	if (!zlib_get_long_option(options, ZEND_STRL("level"), &level)) {
 		RETURN_THROWS();
 	}
diff --git a/ext/zlib/zlib_filter.c b/ext/zlib/zlib_filter.c
index 2d0e4fbb7fa4..4e6c1a54c0f9 100644
--- a/ext/zlib/zlib_filter.c
+++ b/ext/zlib/zlib_filter.c
@@ -361,6 +361,14 @@ static php_stream_filter *php_zlib_filter_create(const char *filtername, zval *f
 	php_zlib_filter_data *data;
 	int status;
 
+	if (filterparams && Z_TYPE_P(filterparams) == IS_OBJECT) {
+		php_error_docref("filters.compression", E_DEPRECATED,
+			"Passing an object for filter parameters for %s is deprecated, call get_object_vars() first instead", filtername);
+		if (UNEXPECTED(EG(exception))) {
+			return NULL;
+		}
+	}
+
 	if (php_stream_filter_parse_write_seek_mode(filterparams, &write_seekable) == FAILURE) {
 		return NULL;
 	}
@@ -368,7 +376,7 @@ static php_stream_filter *php_zlib_filter_create(const char *filtername, zval *f
 	/* Create this filter */
 	data = pecalloc(1, sizeof(php_zlib_filter_data), persistent);
 	if (!data) {
-		php_error_docref(NULL, E_WARNING, "Failed allocating %zd bytes", sizeof(php_zlib_filter_data));
+		php_error_docref("filters.compression", E_WARNING, "Failed allocating %zd bytes", sizeof(php_zlib_filter_data));
 		return NULL;
 	}
 
@@ -380,14 +388,14 @@ static php_stream_filter *php_zlib_filter_create(const char *filtername, zval *f
 	data->strm.avail_out = data->outbuf_len = data->inbuf_len = 0x8000;
 	data->strm.next_in = data->inbuf = (Bytef *) pemalloc(data->inbuf_len, persistent);
 	if (!data->inbuf) {
-		php_error_docref(NULL, E_WARNING, "Failed allocating %zd bytes", data->inbuf_len);
+		php_error_docref("filters.compression", E_WARNING, "Failed allocating %zd bytes", data->inbuf_len);
 		pefree(data, persistent);
 		return NULL;
 	}
 	data->strm.avail_in = 0;
 	data->strm.next_out = data->outbuf = (Bytef *) pemalloc(data->outbuf_len, persistent);
 	if (!data->outbuf) {
-		php_error_docref(NULL, E_WARNING, "Failed allocating %zd bytes", data->outbuf_len);
+		php_error_docref("filters.compression", E_WARNING, "Failed allocating %zd bytes", data->outbuf_len);
 		pefree(data->inbuf, persistent);
 		pefree(data, persistent);
 		return NULL;
@@ -407,7 +415,7 @@ static php_stream_filter *php_zlib_filter_create(const char *filtername, zval *f
 				/* log-2 base of history window (9 - 15) */
 				zend_long tmp = zval_get_long(tmpzval);
 				if (tmp < -MAX_WBITS || tmp > MAX_WBITS + 32) {
-					php_error_docref(NULL, E_WARNING, "Invalid parameter given for window size (" ZEND_LONG_FMT ")", tmp);
+					php_error_docref("filters.compression", E_WARNING, "Invalid parameter given for window size (" ZEND_LONG_FMT ")", tmp);
 				} else {
 					windowBits = tmp;
 				}
@@ -444,7 +452,7 @@ static php_stream_filter *php_zlib_filter_create(const char *filtername, zval *f
 						/* Memory Level (1 - 9) */
 						tmp = zval_get_long(tmpzval);
 						if (tmp < 1 || tmp > MAX_MEM_LEVEL) {
-							php_error_docref(NULL, E_WARNING, "Invalid parameter given for memory level (" ZEND_LONG_FMT ")", tmp);
+							php_error_docref("filters.compression", E_WARNING, "Invalid parameter given for memory level (" ZEND_LONG_FMT ")", tmp);
 						} else {
 							memLevel = tmp;
 						}
@@ -454,7 +462,7 @@ static php_stream_filter *php_zlib_filter_create(const char *filtername, zval *f
 						/* log-2 base of history window (9 - 15) */
 						tmp = zval_get_long(tmpzval);
 						if (tmp < -MAX_WBITS || tmp > MAX_WBITS + 16) {
-							php_error_docref(NULL, E_WARNING, "Invalid parameter given for window size (" ZEND_LONG_FMT ")", tmp);
+							php_error_docref("filters.compression", E_WARNING, "Invalid parameter given for window size (" ZEND_LONG_FMT ")", tmp);
 						} else {
 							windowBits = tmp;
 						}
@@ -475,13 +483,13 @@ static php_stream_filter *php_zlib_filter_create(const char *filtername, zval *f
 factory_setlevel:
 					/* Set compression level within reason (-1 == default, 0 == none, 1-9 == least to most compression */
 					if (tmp < -1 || tmp > 9) {
-						php_error_docref(NULL, E_WARNING, "Invalid compression level specified. (" ZEND_LONG_FMT ")", tmp);
+						php_error_docref("filters.compression", E_WARNING, "Invalid compression level specified. (" ZEND_LONG_FMT ")", tmp);
 					} else {
 						level = tmp;
 					}
 					break;
 				default:
-					php_error_docref(NULL, E_WARNING, "Invalid filter parameter, ignored");
+					php_error_docref("filters.compression", E_WARNING, "Invalid filter parameter, ignored");
 			}
 		}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.