From 0229e619f9e0dca55b7e046fc2c7daa56c795092 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sat, 20 Jun 2026 21:26:09 -0400 Subject: [PATCH] ext/zlib: honor preset dictionary for raw inflate with non-default window inflate_init() applies the preset dictionary eagerly for raw streams via inflateSetDictionary(), gated on encoding == PHP_ZLIB_ENCODING_RAW. But encoding is first adjusted by the window size (encoding += 15 - window), so a raw stream with a non-default window no longer equals PHP_ZLIB_ENCODING_RAW and the dictionary is silently dropped; raw streams carry no header and never emit Z_NEED_DICT, so inflate_add()'s deferred path never applies it either. Gate on the pre-adjustment encoding. The deflate side already applies the dictionary unconditionally, so the roundtrip was broken for this case. --- .../tests/inflate_raw_dictionary_window.phpt | 20 +++++++++++++++++++ ext/zlib/zlib.c | 3 ++- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 ext/zlib/tests/inflate_raw_dictionary_window.phpt diff --git a/ext/zlib/tests/inflate_raw_dictionary_window.phpt b/ext/zlib/tests/inflate_raw_dictionary_window.phpt new file mode 100644 index 000000000000..0269127c1368 --- /dev/null +++ b/ext/zlib/tests/inflate_raw_dictionary_window.phpt @@ -0,0 +1,20 @@ +--TEST-- +inflate_init(): preset dictionary is honored for raw encoding with a non-default window +--EXTENSIONS-- +zlib +--FILE-- + 10, 'dictionary' => $dict]; + +$def = deflate_init(ZLIB_ENCODING_RAW, $opts); +$comp = deflate_add($def, $data, ZLIB_FINISH); + +$inf = inflate_init(ZLIB_ENCODING_RAW, $opts); +$out = inflate_add($inf, $comp, ZLIB_FINISH); + +var_dump($out === $data); +?> +--EXPECT-- +bool(true) diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c index a855dbe769f2..4c899731ab25 100644 --- a/ext/zlib/zlib.c +++ b/ext/zlib/zlib.c @@ -901,6 +901,7 @@ PHP_FUNCTION(inflate_init) ctx->inflateDictlen = dictlen; ctx->status = Z_OK; + zend_long orig_encoding = encoding; if (encoding < 0) { encoding += 15 - window; } else { @@ -914,7 +915,7 @@ PHP_FUNCTION(inflate_init) RETURN_FALSE; } - if (encoding == PHP_ZLIB_ENCODING_RAW && dictlen > 0) { + if (orig_encoding == PHP_ZLIB_ENCODING_RAW && dictlen > 0) { switch (inflateSetDictionary(&ctx->Z, (Bytef *) ctx->inflateDict, ctx->inflateDictlen)) { case Z_OK: efree(ctx->inflateDict);