summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Collins <elic@assurancetechnologies.com>2017-01-22 13:29:30 -0500
committerEli Collins <elic@assurancetechnologies.com>2017-01-22 13:29:30 -0500
commita0edc29cd71556fd8ba53e96b48972588bfc9b25 (patch)
treec1b6fd196a0b30cadacd74923b54c3ef6f0e6491
parent11c6c6d9caa18ef792ee586afb02ae566f528e61 (diff)
downloadpasslib-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.rst3
-rw-r--r--passlib/tests/test_totp.py48
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