[php-src] master: Merge branch 'PHP-8.6'
| From: | ndossche | Date: | Sat, 24 Oct 2026 08:56:02 +0000 |
| Subject: | [php-src] master: Merge branch 'PHP-8.6' | ||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-142660@lists.php.net to get a copy of this message | ||
Author: ndossche (ndossche)
Date: 2026-10-24T10:55:52+02:00
Commit: https://github.com/php/php-src/commit/0c2f56bedfd1ecacf846d176476c0cba9fd2127a
Raw diff: https://github.com/php/php-src/commit/0c2f56bedfd1ecacf846d176476c0cba9fd2127a.diff
Merge branch 'PHP-8.6'
* PHP-8.6:
Fix GOST and Snefru digests of 512 MiB or more
Changed paths:
A ext/hash/tests/gost_snefru_512mib.phpt
M ext/hash/hash_gost.c
M ext/hash/hash_snefru.c
Diff:
diff --git a/ext/hash/hash_gost.c b/ext/hash/hash_gost.c
index 91edbd50834f..f141a58e8a38 100644
--- a/ext/hash/hash_gost.c
+++ b/ext/hash/hash_gost.c
@@ -245,17 +245,12 @@ PHP_HASH_API void PHP_GOSTInitCrypto(PHP_GOST_CTX *context,
ZEND_ATTRIBUTE_UNUSE
context->tables = &tables_crypto;
}
-static const uint32_t MAX32 = 0xffffffffLU;
-
PHP_HASH_API void PHP_GOSTUpdate(PHP_GOST_CTX *context, const unsigned char *input, size_t len)
{
- if ((MAX32 - context->count[0]) < (len * 8)) {
- context->count[1]++;
- context->count[0] = MAX32 - context->count[0];
- context->count[0] = (len * 8) - context->count[0];
- } else {
- context->count[0] += len * 8;
- }
+ uint64_t count = (((uint64_t) context->count[1] << 32) | context->count[0]) +
(uint64_t) len * 8;
+
+ context->count[0] = (uint32_t) count;
+ context->count[1] = (uint32_t) (count >> 32);
if (context->length + len < 32) {
memcpy(&context->buffer[context->length], input, len);
diff --git a/ext/hash/hash_snefru.c b/ext/hash/hash_snefru.c
index 3fe16b4398a3..6ecca3bcb67e 100644
--- a/ext/hash/hash_snefru.c
+++ b/ext/hash/hash_snefru.c
@@ -131,17 +131,12 @@ PHP_HASH_API void PHP_SNEFRUInit(PHP_SNEFRU_CTX *context,
ZEND_ATTRIBUTE_UNUSED
memset(context, 0, sizeof(*context));
}
-static const uint32_t MAX32 = 0xffffffffLU;
-
PHP_HASH_API void PHP_SNEFRUUpdate(PHP_SNEFRU_CTX *context, const unsigned char *input, size_t len)
{
- if ((MAX32 - context->count[1]) < (len * 8)) {
- context->count[0]++;
- context->count[1] = MAX32 - context->count[1];
- context->count[1] = ((uint32_t) len * 8) - context->count[1];
- } else {
- context->count[1] += (uint32_t) len * 8;
- }
+ uint64_t count = (((uint64_t) context->count[0] << 32) | context->count[1]) +
(uint64_t) len * 8;
+
+ context->count[0] = (uint32_t) (count >> 32);
+ context->count[1] = (uint32_t) count;
if (context->length + len < 32) {
memcpy(&context->buffer[context->length], input, len);
diff --git a/ext/hash/tests/gost_snefru_512mib.phpt b/ext/hash/tests/gost_snefru_512mib.phpt
new file mode 100644
index 000000000000..6649140b2722
--- /dev/null
+++ b/ext/hash/tests/gost_snefru_512mib.phpt
@@ -0,0 +1,29 @@
+--TEST--
+Hash: gost and snefru with 512 MiB of input (bit counter carry)
+--SKIPIF--
+<?php
+if (!getenv('RUN_RESOURCE_HEAVY_TESTS')) die('skip resource-heavy test');
+if (getenv('SKIP_SLOW_TESTS')) die('skip slow tests excluded by request');
+?>
+--INI--
+memory_limit=-1
+--FILE--
+<?php
+/* 2^29 bytes are 2^32 bits, so the low word of the bit counter wraps. */
+$chunk = str_repeat('a', 1 << 20);
+foreach (['gost', 'snefru'] as $algo) {
+ $ctx = hash_init($algo);
+ for ($i = 0; $i < 512; $i++) {
+ hash_update($ctx, $chunk);
+ }
+ echo $algo, ': ', hash_final($ctx), "\n";
+}
+unset($chunk);
+
+/* A single update of 2^29 bytes. */
+echo 'snefru: ', hash('snefru', str_repeat('a', 1 << 29)),
"\n";
+?>
+--EXPECT--
+gost: 6c30acc180f544a79c22fa763593a812aec721dd61658b1a5e9a6f3a7955146d
+snefru: 0842a8e735ab08a30149e7e6e34833f365291978ee68c37a5135253b70afa486
+snefru: 0842a8e735ab08a30149e7e6e34833f365291978ee68c37a5135253b70afa486