From d390d7437e69fd6627eb35cf4a45ceee41eed236 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20Backstr=C3=B6m?= Date: Mon, 8 Jun 2026 14:38:04 +0200 Subject: [PATCH] erts: Fix erl_md5 size calculation 32-bit nodes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before the fix there could be an overflow in the size calculation for iolists totaling more than 512 MB. Co-authored-by: Björn Gustavsson --- erts/emulator/beam/erl_md5.c | 4 ++-- erts/emulator/beam/erl_md5.h | 2 +- erts/emulator/test/hash_SUITE.erl | 18 +++++++++++++++++- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/erts/emulator/beam/erl_md5.c b/erts/emulator/beam/erl_md5.c index 1e59260c78f3..eb156fd6351b 100644 --- a/erts/emulator/beam/erl_md5.c +++ b/erts/emulator/beam/erl_md5.c @@ -70,7 +70,7 @@ #define D0 0x10325476 static size_t pad(const uint8_t* last_part, size_t size, uint8_t pad_buf[], - size_t tot_size); + uint64_t tot_size); static void hash_part(const uint8_t* msg_part, erts_md5_state*); void erts_md5_init(erts_md5_state* state) @@ -220,7 +220,7 @@ static void hash_part(const uint8_t* msg_part, erts_md5_state *state) static size_t pad(const uint8_t* last_part, size_t size, uint8_t pad_buf[], - size_t tot_size) + uint64_t tot_size) { size_t filled = (size + 1) % 64; size_t zeroes; diff --git a/erts/emulator/beam/erl_md5.h b/erts/emulator/beam/erl_md5.h index 5a5ba0057348..f9379d55ab17 100644 --- a/erts/emulator/beam/erl_md5.h +++ b/erts/emulator/beam/erl_md5.h @@ -29,7 +29,7 @@ typedef struct { uint32_t a, b, c, d; - size_t tot_len; + uint64_t tot_len; size_t len; uint8_t buf[64]; } erts_md5_state; diff --git a/erts/emulator/test/hash_SUITE.erl b/erts/emulator/test/hash_SUITE.erl index 7e82eb138d61..0bddd0e96466 100644 --- a/erts/emulator/test/hash_SUITE.erl +++ b/erts/emulator/test/hash_SUITE.erl @@ -38,7 +38,7 @@ -export([basic_test/0,cmp_test/1,range_test/0,spread_test/1, phash2_test/0, otp_5292_test/0, otp_7127_test/0, - test_native_record/1, + test_native_record/1, md5_large/1, run_phash2_benchmarks/0, test_phash2_binary_aligned_and_unaligned_equal/1, test_phash2_4GB_plus_bin/1, @@ -114,6 +114,7 @@ all() -> test_phash2_4GB_plus_bin, test_phash2_10MB_plus_bin, test_native_record, + md5_large, {group, phash2_benchmark_tests}, {group, phash2_benchmark}]. @@ -902,6 +903,21 @@ create_record(Rec) -> make_internal_hash(Term) -> erts_debug:get_internal_state({internal_hash, Term}). +md5_large(_Config) when is_list(_Config) -> + %% A type conversion error in the md5 implementation on binaries + %% larger than 512 MB would cause the MD5 be incorrect on + %% 32-bit systems. + + Chunk = <<0:(32*1024*1024)/unit:8>>, + L1 = [<<0>> | lists:duplicate(16, Chunk)], + <<16#EA3B62C6B93CB3625A1FD76777985F5A:128>> = erlang:md5(L1), + + %% 4GB + 1 will not fit in a size_t on 32-bit systems. + L2 = [<<0>> | lists:duplicate(8*16, Chunk)], + <<16#F18C798FF5D450DFE4D3ACDC12B621FF:128>> = erlang:md5(L2), + + ok. + %% %% Reference implementation of integer hashing %%