Skip to content

Commit f5d89c8

Browse files
authored
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.
1 parent 41ecd7c commit f5d89c8

3 files changed

Lines changed: 41 additions & 2 deletions

File tree

‎NEWS‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ PHP NEWS
66
. Use recommended TYPE, HELP order for OpenMetrics metadata.
77
(Marcel Hernandez)
88

9+
- Hash:
10+
. Fixed mhash_keygen_s2k() truncating a $length above INT_MAX instead of
11+
throwing a ValueError. (Marc Bennewitz)
12+
913
- Intl:
1014
. Fixed Collator attribute and strength methods not rejecting an
1115
unconstructed Collator. (Ilia Alshanetsky)

‎ext/hash/hash.c‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1293,12 +1293,18 @@ PHP_FUNCTION(mhash_keygen_s2k)
12931293
RETURN_THROWS();
12941294
}
12951295

1296-
bytes = (int)l_bytes;
1297-
if (bytes <= 0){
1296+
if (l_bytes <= 0) {
12981297
zend_argument_value_error(4, "must be a greater than 0");
12991298
RETURN_THROWS();
13001299
}
13011300

1301+
if (ZEND_LONG_INT_OVFL(l_bytes)) {
1302+
zend_argument_value_error(4, "must be less than or equal to %d", INT_MAX);
1303+
RETURN_THROWS();
1304+
}
1305+
1306+
bytes = (int)l_bytes;
1307+
13021308
salt_len = MIN(salt_len, SALT_SIZE);
13031309

13041310
memcpy(padded_salt, salt, salt_len);

‎ext/hash/tests/gh23950.phpt‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
--TEST--
2+
MHash: GH-23950 (mhash_keygen_s2k() $length must not be truncated to int)
3+
--SKIPIF--
4+
<?php
5+
if (!function_exists('mhash')) die('skip mhash compatibility layer not available');
6+
if (PHP_INT_SIZE == 4) die('skip only where a PHP integer is wider than an int');
7+
?>
8+
--FILE--
9+
<?php
10+
foreach ([2**31, 2**32, 2**32 + 16, PHP_INT_MAX] as $length) {
11+
try {
12+
var_dump(strlen(mhash_keygen_s2k(1, 'password', 'salt', $length)));
13+
} catch (Throwable $e) {
14+
echo $e::class, ': ', $e->getMessage(), "\n";
15+
}
16+
}
17+
?>
18+
--EXPECTF--
19+
Deprecated: Function mhash_keygen_s2k() is deprecated since 8.1 in %s on line %d
20+
ValueError: mhash_keygen_s2k(): Argument #4 ($length) must be less than or equal to 2147483647
21+
22+
Deprecated: Function mhash_keygen_s2k() is deprecated since 8.1 in %s on line %d
23+
ValueError: mhash_keygen_s2k(): Argument #4 ($length) must be less than or equal to 2147483647
24+
25+
Deprecated: Function mhash_keygen_s2k() is deprecated since 8.1 in %s on line %d
26+
ValueError: mhash_keygen_s2k(): Argument #4 ($length) must be less than or equal to 2147483647
27+
28+
Deprecated: Function mhash_keygen_s2k() is deprecated since 8.1 in %s on line %d
29+
ValueError: mhash_keygen_s2k(): Argument #4 ($length) must be less than or equal to 2147483647

0 commit comments

Comments
 (0)