diff options
author | Eli Collins <elic@assurancetechnologies.com> | 2017-01-22 13:29:30 -0500 |
---|---|---|
committer | Eli Collins <elic@assurancetechnologies.com> | 2017-01-22 13:29:30 -0500 |
commit | a0edc29cd71556fd8ba53e96b48972588bfc9b25 (patch) | |
tree | c1b6fd196a0b30cadacd74923b54c3ef6f0e6491 | |
parent | 11c6c6d9caa18ef792ee586afb02ae566f528e61 (diff) | |
download | passlib-a0edc29cd71556fd8ba53e96b48972588bfc9b25.tar.gz |
passlib.tests.test_totp: fixed max_time_t calculation to trap some errors
it was errorneously letting through; also workaround for python 3.6 issue 29346.
-rw-r--r-- | docs/history/1.7.rst | 3 | ||||
-rw-r--r-- | passlib/tests/test_totp.py | 48 |
2 files changed, 42 insertions, 9 deletions
diff --git a/docs/history/1.7.rst b/docs/history/1.7.rst index d84a590..2c0d3b0 100644 --- a/docs/history/1.7.rst +++ b/docs/history/1.7.rst @@ -13,6 +13,9 @@ Passlib 1.7 * bugfix: setup.py: prevent erroneous version strings when run from an sdist. +* bugfix: TOTP tests: test setup now traps additional errors utcfromtimestamp() + may throw under python 3. + .. _whats-new: .. rst-class:: emphasize-children toc-always-open diff --git a/passlib/tests/test_totp.py b/passlib/tests/test_totp.py index 9af4d15..54a9d91 100644 --- a/passlib/tests/test_totp.py +++ b/passlib/tests/test_totp.py @@ -53,15 +53,45 @@ KEY4_RAW = b'Hello!\xde\xad\xbe\xef' assert sys.float_info.radix == 2, "unexpected float_info.radix" assert sys.float_info.mant_dig >= 44, "double precision unexpectedly small" -# work out maximum value acceptable by hosts's time_t -# this is frequently 2**37, though smaller on some systems. -max_time_t = 30 -while True: - try: - datetime.datetime.utcfromtimestamp(max_time_t << 1) - max_time_t <<= 1 - except ValueError: - break +def _get_max_time_t(): + """ + helper to calc max_time_t constant (see below) + """ + value = 1 << 30 # even for 32 bit systems will handle this + year = 0 + while True: + next_value = value << 1 + try: + next_year = datetime.datetime.utcfromtimestamp(next_value-1).year + except (ValueError, OSError, OverflowError): + # utcfromtimestamp() may throw any of the following: + # + # * year out of range for datetime: + # py < 3.6 throws ValueError. + # (py 3.6.0 returns odd value instead, see workaround below) + # + # * int out of range for host's gmtime/localtime: + # py2 throws ValueError, py3 throws OSError. + # + # * int out of range for host's time_t: + # py2 throws ValueError, py3 throws OverflowError. + # + return value-1 + + # Workaround for python 3.6.0 issue -- + # Instead of throwing ValueError if year out of range for datetime, + # Python 3.6 will do some weird behavior that masks high bits + # e.g. (1<<40) -> year 36812, but (1<<41) -> year 6118. + # (Filed as bug -- http://bugs.python.org/issue29346) + # This check stops at largest non-wrapping bit size. + if next_year < year: + return value-1 + + value = next_value + +#: Rough approximation of max value acceptable by hosts's time_t. +#: This is frequently ~2**37 on 64 bit, and ~2**31 on 32 bit systems. +max_time_t = _get_max_time_t() def to_b32_size(raw_size): return (raw_size * 8 + 4) // 5 |