Commit f5d89c83944 for php
commit f5d89c83944b949935fff888b0e3159fc65e4cf1
Author: Marc Bennewitz <marc-mabe@users.noreply.github.com>
Date: Sun Sep 27 23:48:58 2026 +0200
Fix mhash_keygen_s2k() $length truncation to int (#23951)
A $length above INT_MAX was truncated to int before the range check,
so e.g. 2**32 + 16 silently returned 16 bytes. Throw a ValueError instead.
diff --git a/NEWS b/NEWS
index 413c85c2aed..a6e87d987ca 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,10 @@ PHP NEWS
. Use recommended TYPE, HELP order for OpenMetrics metadata.
(Marcel Hernandez)
+- Hash:
+ . Fixed mhash_keygen_s2k() truncating a $length above INT_MAX instead of
+ throwing a ValueError. (Marc Bennewitz)
+
- Intl:
. Fixed Collator attribute and strength methods not rejecting an
unconstructed Collator. (Ilia Alshanetsky)
diff --git a/ext/hash/hash.c b/ext/hash/hash.c
index 8a4e857c9c1..a950d824700 100644
--- a/ext/hash/hash.c
+++ b/ext/hash/hash.c
@@ -1293,12 +1293,18 @@ PHP_FUNCTION(mhash_keygen_s2k)
RETURN_THROWS();
}
- bytes = (int)l_bytes;
- if (bytes <= 0){
+ if (l_bytes <= 0) {
zend_argument_value_error(4, "must be a greater than 0");
RETURN_THROWS();
}
+ if (ZEND_LONG_INT_OVFL(l_bytes)) {
+ zend_argument_value_error(4, "must be less than or equal to %d", INT_MAX);
+ RETURN_THROWS();
+ }
+
+ bytes = (int)l_bytes;
+
salt_len = MIN(salt_len, SALT_SIZE);
memcpy(padded_salt, salt, salt_len);
diff --git a/ext/hash/tests/gh23950.phpt b/ext/hash/tests/gh23950.phpt
new file mode 100644
index 00000000000..d9aa7dea408
--- /dev/null
+++ b/ext/hash/tests/gh23950.phpt
@@ -0,0 +1,29 @@
+--TEST--
+MHash: GH-23950 (mhash_keygen_s2k() $length must not be truncated to int)
+--SKIPIF--
+<?php
+if (!function_exists('mhash')) die('skip mhash compatibility layer not available');
+if (PHP_INT_SIZE == 4) die('skip only where a PHP integer is wider than an int');
+?>
+--FILE--
+<?php
+foreach ([2**31, 2**32, 2**32 + 16, PHP_INT_MAX] as $length) {
+ try {
+ var_dump(strlen(mhash_keygen_s2k(1, 'password', 'salt', $length)));
+ } catch (Throwable $e) {
+ echo $e::class, ': ', $e->getMessage(), "\n";
+ }
+}
+?>
+--EXPECTF--
+Deprecated: Function mhash_keygen_s2k() is deprecated since 8.1 in %s on line %d
+ValueError: mhash_keygen_s2k(): Argument #4 ($length) must be less than or equal to 2147483647
+
+Deprecated: Function mhash_keygen_s2k() is deprecated since 8.1 in %s on line %d
+ValueError: mhash_keygen_s2k(): Argument #4 ($length) must be less than or equal to 2147483647
+
+Deprecated: Function mhash_keygen_s2k() is deprecated since 8.1 in %s on line %d
+ValueError: mhash_keygen_s2k(): Argument #4 ($length) must be less than or equal to 2147483647
+
+Deprecated: Function mhash_keygen_s2k() is deprecated since 8.1 in %s on line %d
+ValueError: mhash_keygen_s2k(): Argument #4 ($length) must be less than or equal to 2147483647