@@ -207,6 +207,11 @@ def hash_constructors(self):
207207 constructors = self .constructors_to_test .values ()
208208 return itertools .chain .from_iterable (constructors )
209209
210+ @property
211+ def shake_constructors (self ):
212+ for shake_name in self .shakes :
213+ yield from self .constructors_to_test .get (shake_name , ())
214+
210215 @property
211216 def is_fips_mode (self ):
212217 return get_fips_mode ()
@@ -376,21 +381,50 @@ def test_hexdigest(self):
376381 self .assertIsInstance (h .digest (), bytes )
377382 self .assertEqual (hexstr (h .digest ()), h .hexdigest ())
378383
379- def test_digest_length_overflow (self ):
380- # See issue #34922
381- large_sizes = (2 ** 29 , 2 ** 32 - 10 , 2 ** 32 + 10 , 2 ** 61 , 2 ** 64 - 10 , 2 ** 64 + 10 )
382- for cons in self .hash_constructors :
383- h = cons (usedforsecurity = False )
384- if h .name not in self .shakes :
385- continue
386- if HASH is not None and isinstance (h , HASH ):
387- # _hashopenssl's take a size_t
388- continue
389- for digest in h .digest , h .hexdigest :
390- self .assertRaises (ValueError , digest , - 10 )
391- for length in large_sizes :
392- with self .assertRaises ((ValueError , OverflowError )):
393- digest (length )
384+ def test_shakes_zero_digest_length (self ):
385+ for constructor in self .shake_constructors :
386+ with self .subTest (constructor = constructor ):
387+ h = constructor (b'abcdef' , usedforsecurity = False )
388+ self .assertEqual (h .digest (0 ), b'' )
389+ self .assertEqual (h .hexdigest (0 ), '' )
390+
391+ def test_shakes_invalid_digest_length (self ):
392+ # See https://github.com/python/cpython/issues/79103.
393+ for constructor in self .shake_constructors :
394+ with self .subTest (constructor = constructor ):
395+ h = constructor (usedforsecurity = False )
396+ # Note: digest() and hexdigest() take a signed input and
397+ # raise if it is negative; the rationale is that we use
398+ # internally PyBytes_FromStringAndSize() and _Py_strhex()
399+ # which both take a Py_ssize_t.
400+ for negative_size in (- 1 , - 10 , - (1 << 31 ), - sys .maxsize ):
401+ self .assertRaises (ValueError , h .digest , negative_size )
402+ self .assertRaises (ValueError , h .hexdigest , negative_size )
403+
404+ def test_shakes_overflow_digest_length (self ):
405+ # See https://github.com/python/cpython/issues/135759.
406+
407+ exc_types = (OverflowError , ValueError )
408+ # HACL* accepts an 'uint32_t' while OpenSSL accepts a 'size_t'.
409+ openssl_overflown_sizes = (sys .maxsize + 1 , 2 * sys .maxsize )
410+ # https://github.com/python/cpython/issues/79103 restricts
411+ # the accepted built-in lengths to 2 ** 29, even if OpenSSL
412+ # accepts such lengths.
413+ builtin_overflown_sizes = openssl_overflown_sizes + (
414+ 2 ** 29 , 2 ** 32 - 10 , 2 ** 32 , 2 ** 32 + 10 ,
415+ 2 ** 61 , 2 ** 64 - 10 , 2 ** 64 , 2 ** 64 + 10 ,
416+ )
417+
418+ for constructor in self .shake_constructors :
419+ with self .subTest (constructor = constructor ):
420+ h = constructor (usedforsecurity = False )
421+ if HASH is not None and isinstance (h , HASH ):
422+ overflown_sizes = openssl_overflown_sizes
423+ else :
424+ overflown_sizes = builtin_overflown_sizes
425+ for invalid_size in overflown_sizes :
426+ self .assertRaises (exc_types , h .digest , invalid_size )
427+ self .assertRaises (exc_types , h .hexdigest , invalid_size )
394428
395429 def test_name_attribute (self ):
396430 for cons in self .hash_constructors :
0 commit comments