Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LWPCookieJar cannot handle cookies with expirations of 2038 or greater on 32-bit platforms #49787

Open
hollec mannequin opened this issue Mar 22, 2009 · 19 comments
Open
Labels
3.8 only security fixes 3.9 only security fixes 3.10 only security fixes stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error

Comments

@hollec
Copy link
Mannequin

hollec mannequin commented Mar 22, 2009

BPO 5537
Nosy @abalkin, @vstinner, @pganssle
Files
  • cookiejar_datetime.patch
  • monkey_patch_cookielib_time2isoz.py
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = None
    created_at = <Date 2009-03-22.17:50:24.659>
    labels = ['3.8', 'type-bug', 'library', '3.9', '3.10']
    title = 'LWPCookieJar cannot handle cookies with expirations of 2038 or greater on 32-bit platforms'
    updated_at = <Date 2020-11-04.02:07:42.993>
    user = 'https://bugs.python.org/hollec'

    bugs.python.org fields:

    activity = <Date 2020-11-04.02:07:42.993>
    actor = 'iritkatriel'
    assignee = 'none'
    closed = False
    closed_date = None
    closer = None
    components = ['Library (Lib)']
    creation = <Date 2009-03-22.17:50:24.659>
    creator = 'hollec'
    dependencies = []
    files = ['20785', '31370']
    hgrepos = []
    issue_num = 5537
    keywords = []
    message_count = 19.0
    messages = ['83979', '105416', '128765', '128781', '128788', '128789', '128791', '128792', '128793', '131603', '131604', '195609', '195610', '361962', '361972', '361978', '361980', '362130', '369219']
    nosy_count = 8.0
    nosy_names = ['jjlee', 'belopolsky', 'vstinner', 'hollec', 'Alex Quinn', 'python-dev', 'p-ganssle', 'nmacleod']
    pr_nums = []
    priority = 'normal'
    resolution = None
    stage = None
    status = 'open'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue5537'
    versions = ['Python 3.8', 'Python 3.9', 'Python 3.10']

    @hollec
    Copy link
    Mannequin Author

    hollec mannequin commented Mar 22, 2009

    The LWPCookieJar can be saved on 64-bit Ubuntu, but not on 32-bit Ubuntu
    when the expiration year is greater than 2038. This has not been tested
    on any other Intel-compatible Linux platform, though it appears related
    to the Year 2038 bug. The MozillaCookieJar does not have a problem
    saving on either architecture.

    A sample crash is shown below:

    File "/home/user/xblstatus/LiveConnect.py", line 189, in connect
    self.cookiejar.save(self.cookieFile)
    File "/usr/lib/python2.5/_LWPCookieJar.py", line 89, in save
    f.write(self.as_lwp_str(ignore_discard, ignore_expires))
    File "/usr/lib/python2.5/_LWPCookieJar.py", line 75, in as_lwp_str
    r.append("Set-Cookie3: %s" % lwp_cookie_str(cookie))
    File "/usr/lib/python2.5/_LWPCookieJar.py", line 35, in lwp_cookie_str
    time2isoz(float(cookie.expires))))
    File "/usr/lib/python2.5/cookielib.py", line 98, in time2isoz
    year, mon, mday, hour, min, sec = time.gmtime(t)[:6]
    ValueError: timestamp out of range for platform time_t

    ---

    The cookie jar and urllib2 integration was done with:

    self.cookiejar = cookielib.LWPCookieJar()
    
    self.opener =
    urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cookiejar))
    
    urllib2.install_opener(self.opener)

    The code used to save the cookie after accessing the web page was:

    self.cookiejar.save(self.cookieFile)

    The cookieFile variable is simply the default location of the cookie
    file for saving in the program.

    @hollec hollec mannequin added the stdlib Python modules in the Lib dir label Mar 22, 2009
    @jjlee
    Copy link
    Mannequin

    jjlee mannequin commented May 9, 2010

    Shouldn't module time be changed to use a cross-platform implementation that uses a 64 bit time_t-like type? Apparently Perl 6 has made the equivalent change.

    Admittedly there seems to be no sign of that actually happening.

    @vstinner
    Copy link
    Member

    Shouldn't module time be changed to use a cross-platform implementation
    that uses a 64 bit time_t-like type? Apparently Perl 6 has made the
    equivalent change.

    The error occurs on time.gmtime(t): even if we use 64 bits time_t type, we have to downcast it to system time_t later, because we would like to call gmtime() function at the end.

    To workaround gmtime() limitation: we can simply use datetime instead. Attached patch replaces gmtime() by datetime.utcfromtimestamp(), and use its .strftime() method which has no such limitation.

    @vstinner
    Copy link
    Member

    Oh, my patch is incomplete: time2netscape() has the same issue.

    @abalkin
    Copy link
    Member

    abalkin commented Feb 18, 2011

    Victor,

    I don't see your patch. Did you remove it?

    @abalkin abalkin added the type-bug An unexpected behavior, bug, or error label Feb 18, 2011
    @vstinner
    Copy link
    Member

    No, I forgot to upload it...

    @abalkin
    Copy link
    Member

    abalkin commented Feb 18, 2011

    While it is unlikely that a purely numeric format such as "%Y-%m-%d
    %H:%M:%S" will be locale dependent, it is possible that some pre-C99
    systems would format dates using exotic digits is some locales. Given
    that format is so simple, I would just use explicit formatting of dt
    components instead of datetime.strftime. Doing so will also eliminate
    a call to system strftime which is known to be quirky on popular
    platforms even in C locale.

    @vstinner
    Copy link
    Member

    If datetime.strftime() is not reliable, we should maybe fix it instead of using a workaround?

    @abalkin
    Copy link
    Member

    abalkin commented Feb 18, 2011

    On Fri, Feb 18, 2011 at 11:04 AM, STINNER Victor <report@bugs.python.org> wrote:
    ..

    If datetime.strftime() is not reliable, we should maybe fix it instead of using a workaround?

    The real fix would be to rewrite strftime so that it does not call
    system strftime. See bpo-3173.

    @python-dev
    Copy link
    Mannequin

    python-dev mannequin commented Mar 21, 2011

    New changeset b15f60f9e256 by Victor Stinner in branch '3.1':
    Issue bpo-5537: Fix time2isoz() and time2netscape() functions of httplib.cookiejar
    http://hg.python.org/cpython/rev/b15f60f9e256

    @vstinner
    Copy link
    Member

    While it is unlikely that a purely numeric format such as "%Y-%m-%d
    %H:%M:%S" will be locale dependent, it is possible that some pre-C99
    systems would format dates using exotic digits is some locales.

    Ok, I rewrote my patch to avoid strftime(). It should now be fixed.

    FYI datetime.fromtimestamp() converts the timestamp to a double, which has a precision of 53 bits (no precision loss for year < 285,422,890 and so it's enough for year 2038).

    @AlexQuinn
    Copy link
    Mannequin

    AlexQuinn mannequin commented Aug 19, 2013

    This bug still exists in Python 2.7.3 32-bit on Linux.

    I wonder if this might be because the patch (posted 2011-02-18) used utcfromtimestamp(). datetime.datetime.utcfromtimestamp(2**32) will fail on 32-bit systems.

    The bug does NOT exist in Python 2.7.3 32-bit on Windows (64-bit OS).

    ==========================================
    32-BIT PYTHON ON 32-BIT LINUX
    ------------------------------------------

    $ python -c "import sys, cookielib; print sys.version; print cookielib.time2isoz(2322923767)"
    2.7.3 (default, Apr 10 2013, 05:46:21) 
    [GCC 4.6.3]
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/usr/lib/python2.7/cookielib.py", line 99, in time2isoz
        year, mon, mday, hour, min, sec = time.gmtime(t)[:6]
    ValueError: timestamp out of range for platform time_t
    ==========================================
    
    
    

    ==========================================
    64-BIT PYTHON ON 64-BIT LINUX
    ------------------------------------------

    $ python -c "import sys, cookielib; print sys.version; print cookielib.time2isoz(2322923767)"
    2.7.3 (default, Aug  3 2012, 17:21:07)
    [GCC 4.1.2 20080704 (Red Hat 4.1.2-52)]
    2043-08-11 16:36:07Z
    ==========================================
    
    
    

    ==========================================
    32-BIT PYTHON ON 64-BIT WINDOWS
    ------------------------------------------
    C:\>python -c "import sys, cookielib; print sys.version; print cookielib.time2isoz(2322923767)"
    2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32 bit (Intel)]
    2043-08-11 16:36:07Z
    ==========================================

    @AlexQuinn
    Copy link
    Mannequin

    AlexQuinn mannequin commented Aug 19, 2013

    For those who are affected by this bug, here's a snippet to monkey-patch cookielib on any Python 2.4 to 2.7.

    A more complete version of this was attached to my message a moment ago.

    ==========================================

    import cookielib
    try:
        cookielib.time2isoz(2**32)
    except ValueError:
        from datetime import datetime, timedelta
        def time2isoz(t=None):
            if t is None:
                dt = datetime.now()
            else:
                dt = datetime.utcfromtimestamp(0) + timedelta(seconds=int(t))
            return "%04d-%02d-%02d %02d:%02d:%02dZ"%\
                    (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second)
        cookielib.time2isoz = time2isoz

    ==========================================

    @nmacleod
    Copy link
    Mannequin

    nmacleod mannequin commented Feb 13, 2020

    Apologies for the necro on this issue, but should this now be fixed in Python3.7? As it appears to still be an issue.

    Testing on a Raspberry Pi with LibreELEC (32-bit OS):

    rpi512:~ # python -c "import sys, http.cookiejar; print(sys.version); print(http.cookiejar.time2isoz(2322923767))"
    3.7.6 (default, Feb 12 2020, 17:36:39)
    [GCC 9.2.0]
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/usr/lib/python3.7/cookiejar.py", line 101, in time2isoz
    OverflowError: timestamp out of range for platform time_t

    This is on a distribution built with latest glibc-2.31.

    @vstinner
    Copy link
    Member

    Oh, maybe the bug wasn't properly fixed?

    Can you please try the patch above?

    diff --git a/Lib/http/cookiejar.py b/Lib/http/cookiejar.py
    index 47ed5c3d64..55915cf18a 100644
    --- a/Lib/http/cookiejar.py
    +++ b/Lib/http/cookiejar.py
    @@ -99,7 +99,7 @@ def time2isoz(t=None):
         if t is None:
             dt = datetime.datetime.utcnow()
         else:
    -        dt = datetime.datetime.utcfromtimestamp(t)
    +        dt = datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=t)
         return "%04d-%02d-%02d %02d:%02d:%02dZ" % (
             dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second)
     

    For example, copy http/ subdirectory in the current directory, and then patch manually http/cookiejar.py file.

    @vstinner vstinner reopened this Feb 13, 2020
    @nmacleod
    Copy link
    Mannequin

    nmacleod mannequin commented Feb 14, 2020

    Hi Victor

    I can confirm the patch is working on both 32-bit and 64-bit systems running Python3.7.6, with both platforms returning the same result after patching - many thanks!

    #### UNPATCHED, 32-bit (RPi3+)
    LibreELEC (Milhouse.testing): devel-20200213234919-#0213f-g70b69eb (RPi2.arm)
    rpi22:~ # python -c "import sys, http.cookiejar; print(sys.version); print(http.cookiejar.time2isoz(2322923767))"
    3.7.6 (default, Feb 14 2020, 00:35:22)
    [GCC 9.2.0]
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/usr/lib/python3.7/cookiejar.py", line 101, in time2isoz
    OverflowError: timestamp out of range for platform time_t

    #### PATCHED, 32-bit (RPi3+)
    LibreELEC (Milhouse.testing): devel-20200214012134-#0213g-g70b69eb (RPi2.arm)
    rpi22:~ # python -c "import sys, http.cookiejar; print(sys.version); print(http.cookiejar.time2isoz(2322923767))"
    3.7.6 (default, Feb 14 2020, 01:22:50)
    [GCC 9.2.0]
    2043-08-11 16:36:07Z

    #### UNPATCHED, 64-bit (x86_64)
    LibreELEC (Milhouse.next): devel-20200213053123-#0212x-g67aedc9 (Generic.x86_64)
    NUC:~ # python -c "import sys, http.cookiejar; print(sys.version); print(http.cookiejar.time2isoz(2322923767))"
    3.7.6 (default, Feb 12 2020, 20:54:03)
    [GCC 9.2.0]
    2043-08-11 16:36:07Z

    #### PATCHED, 64-bit (x86_64)
    LibreELEC (Milhouse.next): devel-20200214005606-bpo-0214-g70b69eb (Generic.x86_64)
    NUC:~ # python -c "import sys, http.cookiejar; print(sys.version); print(http.cookiejar.time2isoz(2322923767))"
    3.7.6 (default, Feb 14 2020, 01:00:37)
    [GCC 9.2.0]
    2043-08-11 16:36:07Z

    @nmacleod
    Copy link
    Mannequin

    nmacleod mannequin commented Feb 14, 2020

    Just an FYI, this is also broken on 32-bit with Python2.7.16, so possibly it was never fixed originally (rather than being a regression).

    LibreELEC (Milhouse): devel-20191012235627-#1012-ge416c8b (RPi2.arm)
    rpi22:~ # python -c "import sys, cookielib; print sys.version; print cookielib.time2isoz(2322923767)"
    2.7.16 (default, Sep 29 2019, 04:11:31)
    [GCC 9.2.0]
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/usr/lib/python2.7/cookielib.py", line 99, in time2isoz
    ValueError: timestamp out of range for platform time_t

    @vstinner
    Copy link
    Member

    @paul Ganssle: it's a little sad that I have work around datetime.datetime.utcfromtimestamp() function to avoid an OverflowError exception: msg361972.

    Should we fix utcfromtimestamp() internally to avoid the OverflowError, rather than only fixing the http.cookiejar module?

    @pganssle
    Copy link
    Member

    Should we fix utcfromtimestamp() internally to avoid the OverflowError, rather than only fixing the http.cookiejar module?

    I'm not a big fan of utcfromtimestamp (as you can see here: https://blog.ganssle.io/articles/2019/11/utcnow.html ), but it seems we do have the same issue in datetime.datetime.fromtimestamp, so I think maybe we should spawn a new issue to at least look into the possibility?

    @iritkatriel iritkatriel added 3.8 only security fixes 3.9 only security fixes 3.10 only security fixes labels Nov 4, 2020
    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    3.8 only security fixes 3.9 only security fixes 3.10 only security fixes stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error
    Projects
    Status: No status
    Development

    No branches or pull requests

    4 participants