From d053624aa8534c984e07d4d8d2ee867de013e2ec Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Mon, 24 Jan 2011 08:02:40 +0000 Subject: [PATCH] Fixed #15067 -- Modified the range checks on base36_to_int so you are guaranteed to always get an int, avoiding possible OverflowErrors. Thanks to Garthex for the report, jboutros for the patch, and kfrazier for the feedback. git-svn-id: http://code.djangoproject.com/svn/django/trunk@15288 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/contrib/auth/tests/views.py | 6 ++++++ django/utils/http.py | 16 +++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/django/contrib/auth/tests/views.py b/django/contrib/auth/tests/views.py index 014c8195fc..b4f93cefc3 100644 --- a/django/contrib/auth/tests/views.py +++ b/django/contrib/auth/tests/views.py @@ -104,6 +104,12 @@ class PasswordResetTest(AuthViewsTestCase): self.assertEquals(response.status_code, 200) self.assert_("The password reset link was invalid" in response.content) + def test_confirm_overflow_user(self): + # Ensure that we get a 200 response for a base36 user id that overflows int + response = self.client.get('/reset/zzzzzzzzzzzzz-1-1/') + self.assertEquals(response.status_code, 200) + self.assert_("The password reset link was invalid" in response.content) + def test_confirm_invalid_post(self): # Same as test_confirm_invalid, but trying # to do a POST instead. diff --git a/django/utils/http.py b/django/utils/http.py index e18d8dd29c..1384b4294c 100644 --- a/django/utils/http.py +++ b/django/utils/http.py @@ -1,4 +1,5 @@ import re +import sys import urllib from email.Utils import formatdate @@ -73,14 +74,19 @@ def http_date(epoch_seconds=None): def base36_to_int(s): """ - Converts a base 36 string to an ``int``. To prevent - overconsumption of server resources, raises ``ValueError` if the - input is longer than 13 base36 digits (13 digits is sufficient to - base36-encode any 64-bit integer). + Converts a base 36 string to an ``int``. Raises ``ValueError` if the + input won't fit into an int. """ + # To prevent overconsumption of server resources, reject any + # base36 string that is long than 13 base36 digits (13 digits + # is sufficient to base36-encode any 64-bit integer) if len(s) > 13: raise ValueError("Base36 input too large") - return int(s, 36) + value = int(s, 36) + # ... then do a final check that the value will fit into an int. + if value > sys.maxint: + raise ValueError("Base36 input too large") + return value def int_to_base36(i): """