From 39873b7e586a508100d40672b4e5cdb10833d0a5 Mon Sep 17 00:00:00 2001 From: ndossche Date: Thu, 13 Feb 2025 16:53:43 +0100 Subject: [PATCH] Fix memory leak when encoding check fails zlib_create_dictionary_string() allocates memory, so we can leak memory if there's an early exit before the assignment to the return value. Solve this by moving all validation upwards. --- .../leak_invalid_encoding_with_dict.phpt | 20 +++++++++++++++++++ ext/zlib/zlib.c | 16 +++++++-------- 2 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 ext/zlib/tests/leak_invalid_encoding_with_dict.phpt diff --git a/ext/zlib/tests/leak_invalid_encoding_with_dict.phpt b/ext/zlib/tests/leak_invalid_encoding_with_dict.phpt new file mode 100644 index 000000000000..da2a11849c0c --- /dev/null +++ b/ext/zlib/tests/leak_invalid_encoding_with_dict.phpt @@ -0,0 +1,20 @@ +--TEST-- +Memory leak when passing a dictionary with invalid encoding +--EXTENSIONS-- +zlib +--FILE-- + "dict"]); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +try { + deflate_init(123456, ["dictionary" => "dict"]); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +?> +--EXPECT-- +Encoding mode must be ZLIB_ENCODING_RAW, ZLIB_ENCODING_GZIP or ZLIB_ENCODING_DEFLATE +deflate_init(): Argument #1 ($encoding) must be one of ZLIB_ENCODING_RAW, ZLIB_ENCODING_GZIP, or ZLIB_ENCODING_DEFLATE diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c index 98b2fd6fe6ce..a97d32c6d43e 100644 --- a/ext/zlib/zlib.c +++ b/ext/zlib/zlib.c @@ -879,10 +879,6 @@ PHP_FUNCTION(inflate_init) RETURN_THROWS(); } - if (!zlib_create_dictionary_string(options, &dict, &dictlen)) { - RETURN_THROWS(); - } - switch (encoding) { case PHP_ZLIB_ENCODING_RAW: case PHP_ZLIB_ENCODING_GZIP: @@ -893,6 +889,10 @@ PHP_FUNCTION(inflate_init) RETURN_THROWS(); } + if (!zlib_create_dictionary_string(options, &dict, &dictlen)) { + RETURN_THROWS(); + } + object_init_ex(return_value, inflate_context_ce); ctx = Z_INFLATE_CONTEXT_P(return_value); @@ -1132,10 +1132,6 @@ PHP_FUNCTION(deflate_init) RETURN_THROWS(); } - if (!zlib_create_dictionary_string(options, &dict, &dictlen)) { - RETURN_THROWS(); - } - switch (encoding) { case PHP_ZLIB_ENCODING_RAW: case PHP_ZLIB_ENCODING_GZIP: @@ -1146,6 +1142,10 @@ PHP_FUNCTION(deflate_init) RETURN_THROWS(); } + if (!zlib_create_dictionary_string(options, &dict, &dictlen)) { + RETURN_THROWS(); + } + object_init_ex(return_value, deflate_context_ce); ctx = Z_DEFLATE_CONTEXT_P(return_value);