Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions tornado/test/web_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2866,6 +2866,35 @@ def validate(sig):
)
)

def test_malformed_timestamp(self):
# A structurally valid v2 value carrying a correct signature but a
# non-decimal timestamp field must be rejected with None rather than
# raising ValueError from int(timestamp_bytes) after the signature has
# already verified.
from tornado.web import _create_signature_v2
from tornado.escape import utf8

def field(value):
return str(len(value)).encode("ascii") + b":" + value

name = "key"
prefix = b"|".join(
[
b"2",
field(b"0"),
field(b"a"), # non-decimal timestamp
field(utf8(name)),
field(b""),
b"",
]
)
cookie = prefix + _create_signature_v2(SignedValueTest.SECRET, prefix)
self.assertIsNone(
decode_signed_value(
SignedValueTest.SECRET, name, cookie, clock=self.present
)
)

def test_non_ascii(self):
value = b"\xe9"
signed = create_signed_value(
Expand Down
8 changes: 7 additions & 1 deletion tornado/web.py
Original file line number Diff line number Diff line change
Expand Up @@ -3767,7 +3767,13 @@ def _decode_signed_value_v2(
return None
if name_field != utf8(name):
return None
timestamp = int(timestamp_bytes)
try:
timestamp = int(timestamp_bytes)
except ValueError:
# A malformed (non-decimal) timestamp field means an invalid signed
# value; reject it with None rather than raising, consistent with the
# rest of this function and get_signed_cookie's documented behavior.
return None
if timestamp < clock() - max_age_days * 86400:
# The signature has expired.
return None
Expand Down