Commit fb76b3d7158 for php.net

commit fb76b3d7158647d2c96fdcf2f5a2feb01d04b425
Author: Ilia Alshanetsky <ilia@ilia.ws>
Date:   Sat Jun 20 21:26:09 2026 -0400

    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.

    Closes GH-22381

diff --git a/NEWS b/NEWS
index 39010ac77b1..41e9dd50699 100644
--- a/NEWS
+++ b/NEWS
@@ -62,6 +62,10 @@ PHP                                                                        NEWS
     PROCESS_INFORMATION, an indeterminate comspec pointer after a failed
     lookup, and an unchecked CreateFileA() failure. (Ilia Alshanetsky)

+- Zlib:
+  . Fixed inflate_init() dropping the preset dictionary for raw streams with
+    a non-default window. (Ilia Alshanetsky)
+

 24 Sep 2026, PHP 8.5.11

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 00000000000..0269127c136
--- /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--
+<?php
+$dict = "the quick brown fox jumps over the lazy dog";
+$data = str_repeat($dict . " ", 8);
+$opts = ['window' => 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 b221b1f4b55..003ffa80111 100644
--- a/ext/zlib/zlib.c
+++ b/ext/zlib/zlib.c
@@ -904,6 +904,7 @@ PHP_FUNCTION(inflate_init)
 	ctx->inflateDictlen = dictlen;
 	ctx->status = Z_OK;

+	zend_long orig_encoding = encoding;
 	if (encoding < 0) {
 		encoding += 15 - window;
 	} else {
@@ -917,7 +918,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);