From d25c793ccd7498246ce6dab305c7693e879f80dd Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Fri, 23 Oct 2026 22:28:39 -0700 Subject: [PATCH] Keep the given running value in Zlib.crc32(nil, crc) and Zlib.adler32(nil, adler) For a nil string the checksum was computed as crc32(crc, NULL, 0), but zlib returns the initial value whenever the buffer is NULL, discarding the running value that was passed in. ```ruby Zlib.crc32(nil, 1234) # expected: 1234 (as Zlib.crc32("", 1234)) # actual: 0 Zlib.adler32(nil, 1234) # expected: 1234 # actual: 1 ``` Co-Authored-By: Claude Mythos 5.1 --- ext/zlib/zlib.c | 4 +++- test/zlib/test_zlib.rb | 9 +++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c index 982933b..0163129 100644 --- a/ext/zlib/zlib.c +++ b/ext/zlib/zlib.c @@ -434,7 +434,9 @@ do_checksum(int argc, VALUE *argv, checksum_func func) } if (NIL_P(str)) { - sum = func(mask32(sum), Z_NULL, 0); + /* zlib returns the initial value for a NULL buffer, which would discard + * an explicitly given running checksum; behave like an empty string */ + sum = NIL_P(vsum) ? func(0, Z_NULL, 0) : func(mask32(sum), (const Bytef *)"", 0); } else if (rb_obj_is_kind_of(str, rb_cIO)) { VALUE buf; diff --git a/test/zlib/test_zlib.rb b/test/zlib/test_zlib.rb index 1f9cb81..efacd24 100644 --- a/test/zlib/test_zlib.rb +++ b/test/zlib/test_zlib.rb @@ -1647,6 +1647,15 @@ def test_crc32_combine end end + def test_checksum_nil_with_initial_value + assert_equal(Zlib.crc32("", 1234), Zlib.crc32(nil, 1234)) + assert_equal(1234, Zlib.crc32(nil, 1234)) # was 0 + assert_equal(1234, Zlib.adler32(nil, 1234)) # was 1 + assert_equal(Zlib.adler32("", 2**31 - 1), Zlib.adler32(nil, 2**31 - 1)) + assert_equal(0, Zlib.crc32(nil)) + assert_equal(1, Zlib.adler32(nil)) + end + def test_crc_table t = Zlib.crc_table assert_instance_of(Array, t)