|
12 | 12 | import itertools
|
13 | 13 | import logging
|
14 | 14 | import os
|
| 15 | +import re |
15 | 16 | import sys
|
16 | 17 | import sysconfig
|
17 | 18 | import tempfile
|
@@ -141,11 +142,10 @@ def __init__(self, *args, **kwargs):
|
141 | 142 | # of hashlib.new given the algorithm name.
|
142 | 143 | for algorithm, constructors in self.constructors_to_test.items():
|
143 | 144 | constructors.add(getattr(hashlib, algorithm))
|
144 |
| - def _test_algorithm_via_hashlib_new(data=None, _alg=algorithm, **kwargs): |
145 |
| - if data is None: |
146 |
| - return hashlib.new(_alg, **kwargs) |
147 |
| - return hashlib.new(_alg, data, **kwargs) |
148 |
| - constructors.add(_test_algorithm_via_hashlib_new) |
| 145 | + def c(*args, __algorithm_name=algorithm, **kwargs): |
| 146 | + return hashlib.new(__algorithm_name, *args, **kwargs) |
| 147 | + c.__name__ = f'do_test_algorithm_via_hashlib_new_{algorithm}' |
| 148 | + constructors.add(c) |
149 | 149 |
|
150 | 150 | _hashlib = self._conditional_import_module('_hashlib')
|
151 | 151 | self._hashlib = _hashlib
|
@@ -250,6 +250,75 @@ def test_usedforsecurity_false(self):
|
250 | 250 | self._hashlib.new("md5", usedforsecurity=False)
|
251 | 251 | self._hashlib.openssl_md5(usedforsecurity=False)
|
252 | 252 |
|
| 253 | + @unittest.skipIf(get_fips_mode(), "skip in FIPS mode") |
| 254 | + def test_clinic_signature(self): |
| 255 | + for constructor in self.hash_constructors: |
| 256 | + with self.subTest(constructor.__name__): |
| 257 | + constructor(b'') |
| 258 | + constructor(data=b'') |
| 259 | + constructor(string=b'') # should be deprecated in the future |
| 260 | + |
| 261 | + digest_name = constructor(b'').name |
| 262 | + with self.subTest(digest_name): |
| 263 | + hashlib.new(digest_name, b'') |
| 264 | + hashlib.new(digest_name, data=b'') |
| 265 | + hashlib.new(digest_name, string=b'') |
| 266 | + if self._hashlib: |
| 267 | + self._hashlib.new(digest_name, b'') |
| 268 | + self._hashlib.new(digest_name, data=b'') |
| 269 | + self._hashlib.new(digest_name, string=b'') |
| 270 | + |
| 271 | + @unittest.skipIf(get_fips_mode(), "skip in FIPS mode") |
| 272 | + def test_clinic_signature_errors(self): |
| 273 | + nomsg = b'' |
| 274 | + mymsg = b'msg' |
| 275 | + conflicting_call = re.escape( |
| 276 | + "'data' and 'string' are mutually exclusive " |
| 277 | + "and support for 'string' keyword parameter " |
| 278 | + "is slated for removal in a future version." |
| 279 | + ) |
| 280 | + duplicated_param = re.escape("given by name ('data') and position") |
| 281 | + unexpected_param = re.escape("got an unexpected keyword argument '_'") |
| 282 | + for args, kwds, errmsg in [ |
| 283 | + # Reject duplicated arguments before unknown keyword arguments. |
| 284 | + ((nomsg,), dict(data=nomsg, _=nomsg), duplicated_param), |
| 285 | + ((mymsg,), dict(data=nomsg, _=nomsg), duplicated_param), |
| 286 | + # Reject duplicated arguments before conflicting ones. |
| 287 | + *itertools.product( |
| 288 | + [[nomsg], [mymsg]], |
| 289 | + [dict(data=nomsg), dict(data=nomsg, string=nomsg)], |
| 290 | + [duplicated_param] |
| 291 | + ), |
| 292 | + # Reject unknown keyword arguments before conflicting ones. |
| 293 | + *itertools.product( |
| 294 | + [()], |
| 295 | + [ |
| 296 | + dict(_=None), |
| 297 | + dict(data=nomsg, _=None), |
| 298 | + dict(string=nomsg, _=None), |
| 299 | + dict(string=nomsg, data=nomsg, _=None), |
| 300 | + ], |
| 301 | + [unexpected_param] |
| 302 | + ), |
| 303 | + ((nomsg,), dict(_=None), unexpected_param), |
| 304 | + ((mymsg,), dict(_=None), unexpected_param), |
| 305 | + # Reject conflicting arguments. |
| 306 | + [(nomsg,), dict(string=nomsg), conflicting_call], |
| 307 | + [(mymsg,), dict(string=nomsg), conflicting_call], |
| 308 | + [(), dict(data=nomsg, string=nomsg), conflicting_call], |
| 309 | + ]: |
| 310 | + for constructor in self.hash_constructors: |
| 311 | + digest_name = constructor(b'').name |
| 312 | + with self.subTest(constructor.__name__, args=args, kwds=kwds): |
| 313 | + with self.assertRaisesRegex(TypeError, errmsg): |
| 314 | + constructor(*args, **kwds) |
| 315 | + with self.subTest(digest_name, args=args, kwds=kwds): |
| 316 | + with self.assertRaisesRegex(TypeError, errmsg): |
| 317 | + hashlib.new(digest_name, *args, **kwds) |
| 318 | + if self._hashlib: |
| 319 | + with self.assertRaisesRegex(TypeError, errmsg): |
| 320 | + self._hashlib.new(digest_name, *args, **kwds) |
| 321 | + |
253 | 322 | def test_unknown_hash(self):
|
254 | 323 | self.assertRaises(ValueError, hashlib.new, 'spam spam spam spam spam')
|
255 | 324 | self.assertRaises(TypeError, hashlib.new, 1)
|
@@ -719,8 +788,6 @@ def check_blake2(self, constructor, salt_size, person_size, key_size,
|
719 | 788 | self.assertRaises(ValueError, constructor, node_offset=-1)
|
720 | 789 | self.assertRaises(OverflowError, constructor, node_offset=max_offset+1)
|
721 | 790 |
|
722 |
| - self.assertRaises(TypeError, constructor, data=b'') |
723 |
| - self.assertRaises(TypeError, constructor, string=b'') |
724 | 791 | self.assertRaises(TypeError, constructor, '')
|
725 | 792 |
|
726 | 793 | constructor(
|
|
0 commit comments