From a9d42b218f7cca9fe3581b7797107c22b4d738c0 Mon Sep 17 00:00:00 2001 From: Saiyam Jain Date: Mon, 26 Oct 2026 18:54:21 +0530 Subject: [PATCH] fix(hashes): evaluate adler32 over bytes to resolve non-ASCII divergence (fixes #15635) --- hashes/adler32.py | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/hashes/adler32.py b/hashes/adler32.py index 38d76ab12aa0..7b94434a8ca2 100644 --- a/hashes/adler32.py +++ b/hashes/adler32.py @@ -11,20 +11,56 @@ MOD_ADLER = 65521 -def adler32(plain_text: str) -> int: +def adler32(plain_text: str | bytes) -> int: """ Function implements adler-32 hash. - Iterates and evaluates a new value for each character + Iterates and evaluates a new value for each byte in the data. + If a string is passed, it is encoded to UTF-8 bytes per the Adler-32 specification. >>> adler32('Algorithms') 363791387 >>> adler32('go adler em all') 708642122 + + >>> adler32('€100') + 196018850 + + >>> adler32(b'Algorithms') + 363791387 + + >>> adler32(b'') + 1 + + >>> adler32('') + 1 + + >>> import zlib + >>> adler32('日本語テスト') == zlib.adler32('日本語テスト'.encode()) + True + + >>> adler32(b'\\x00\\xff\\xfe') == zlib.adler32(b'\\x00\\xff\\xfe') + True + + >>> adler32(123) + Traceback (most recent call last): + ... + TypeError: plain_text must be str or bytes-like, not int """ + if not isinstance(plain_text, (str, bytes, bytearray)): + msg = f"plain_text must be str or bytes-like, not {type(plain_text).__name__}" + raise TypeError(msg) + + data = plain_text.encode("utf-8") if isinstance(plain_text, str) else plain_text a = 1 b = 0 - for plain_chr in plain_text: - a = (a + ord(plain_chr)) % MOD_ADLER + for byte in data: + a = (a + byte) % MOD_ADLER b = (b + a) % MOD_ADLER return (b << 16) | a + + +if __name__ == "__main__": + import doctest + + doctest.testmod()