From dec539f36017fecbd749a268e4aea4b2598a3997 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Mon, 24 Jan 2011 08:04:14 +0000 Subject: [PATCH] [1.2.X] 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. Backport of r15288 from trunk. git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.2.X@15289 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 22fdbd6eaf..a5d0262114 100644 --- a/django/contrib/auth/tests/views.py +++ b/django/contrib/auth/tests/views.py @@ -88,6 +88,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 2fb60078e5..49d067e57c 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): """