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

Bug found in datetime for Epoch time = -1 #45007

Closed
blais mannequin opened this issue May 28, 2007 · 20 comments
Closed

Bug found in datetime for Epoch time = -1 #45007

blais mannequin opened this issue May 28, 2007 · 20 comments
Assignees
Labels
extension-modules C modules in the Modules dir type-bug An unexpected behavior, bug, or error

Comments

@blais
Copy link
Mannequin

blais mannequin commented May 28, 2007

BPO 1726687
Nosy @loewis, @amauryfa, @abalkin, @vstinner
Files
  • timebug.py: reproduce the bug
  • timebug.c: chech mktime()'s behaviour
  • timebug.patch: the patch that pretends to fix this nasty buggerdibug bug!
  • mktime_fix_and_tests.patch
  • fix_mktime-2.patch
  • 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 = 'https://github.com/abalkin'
    closed_at = <Date 2011-02-16.18:57:10.410>
    created_at = <Date 2007-05-28.02:27:51.000>
    labels = ['extension-modules', 'type-bug']
    title = 'Bug found in datetime for Epoch time = -1'
    updated_at = <Date 2011-02-16.18:57:10.409>
    user = 'https://bugs.python.org/blais'

    bugs.python.org fields:

    activity = <Date 2011-02-16.18:57:10.409>
    actor = 'belopolsky'
    assignee = 'belopolsky'
    closed = True
    closed_date = <Date 2011-02-16.18:57:10.410>
    closer = 'belopolsky'
    components = ['Extension Modules']
    creation = <Date 2007-05-28.02:27:51.000>
    creator = 'blais'
    dependencies = []
    files = ['8011', '8012', '8013', '11982', '13378']
    hgrepos = []
    issue_num = 1726687
    keywords = ['patch', 'needs review']
    message_count = 20.0
    messages = ['52686', '52687', '52688', '52689', '52690', '52691', '75728', '75901', '75918', '80797', '80799', '83838', '83863', '83864', '99528', '99540', '108045', '108054', '125976', '128689']
    nosy_count = 5.0
    nosy_names = ['loewis', 'amaury.forgeotdarc', 'blais', 'belopolsky', 'vstinner']
    pr_nums = []
    priority = 'low'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue1726687'
    versions = ['Python 3.1', 'Python 3.2']

    @blais
    Copy link
    Mannequin Author

    blais mannequin commented May 28, 2007

    There is a bug in datetime.fromtimestamp(), whereby if it is called with -1, it fails with "mktime argument out of range" when it should not (see attached test program to reproduce the problem).

    The bug is that the way that mktime() signals an error code is subtle and error-prone: you need to set a sentinel in the tm's wday or yday and not only check the return value of mktime, but also check if those values have been modified; it figures: -1 is a valid value in the return domain of mktime() and is not a sufficient condition for signaling an error.

    Here is the relevant excerpt from the Linux man page:

       The mktime() function converts a broken-down time structure,  expressed
       as  local  time, to calendar time representation.  The function ignores
       the specified contents of the structure members tm_wday and tm_yday and
       recomputes  them  from  the  other  information in the broken-down time
       structure.  If structure members are outside their legal interval, they
       will  be normalized (so that, e.g., 40 October is changed into 9 Novem-
       ber).  Calling mktime() also sets the  external  variable  tzname  with
       information  about the current time zone.  If the specified broken-down
       time cannot be represented as calendar time (seconds since the  epoch),
       mktime() returns a value of (time_t)(-1) and does not alter the tm_wday
       and tm_yday members of the broken-down time structure.
    

    This was found under Linux, I do not know if this bug also occurs on Windows or the Mac.

    I attached a couple of files:

    • timebug.py: reproduce the bug
    • timebug.c: tests that mktime()'s behaviour is as wicked as expected
    • timebug.patch: the fix to the datetime module.

    P.S. I hit this bug in a graphics application while zooming in/out of a viewer rendering time-based data. Sheer luck.

    @blais
    Copy link
    Mannequin Author

    blais mannequin commented May 28, 2007

    File Added: timebug.py

    @blais
    Copy link
    Mannequin Author

    blais mannequin commented May 28, 2007

    File Added: timebug.c

    @blais
    Copy link
    Mannequin Author

    blais mannequin commented May 28, 2007

    File Added: timebug.patch

    @blais
    Copy link
    Mannequin Author

    blais mannequin commented May 28, 2007

    (Additional note: this bug was found and fixed with Peter Wang from Enthought.)

    @loewis
    Copy link
    Mannequin

    loewis mannequin commented May 29, 2007

    Reclassifying as a patch.

    @vstinner
    Copy link
    Member

    The patch is correct. I tried to use errno, but errno is unchanged on
    error. Here is a new patch with regression tests.

    @vstinner
    Copy link
    Member

    Can anyone review the last patch?

    @amauryfa
    Copy link
    Member

    on Windows (with Visual Studio), mktime() also sets tm_wday only if
    successful.

    But negative time_t are still not allowed by the Microsoft CRT, the
    tests fail.
    There are workaround to this - for example python could use techniques
    similar to http://robertinventor.com/software/t64/

    OTOH, the docs of the time module explicitly says that dates before the
    Epoch are not handled. Do you want to change this? in other words: is
    this a bug or a feature request?
    http://docs.python.org/library/time.html

    @vstinner
    Copy link
    Member

    But negative time_t are still not allowed by the Microsoft CRT,
    the tests fail.
    (...)
    is this a bug or a feature request?

    Linux mktime() supports any timestamp from 1901..2038. Should we limit
    the timestamp to 1970 just because of Microsoft? Test tm_wday fixes a
    bug on Linux and doesn't change the behaviour on Windows. So the
    problem is just the unit test: the test should be different on Windows
    (make sure that -1 raises an error).

    @vstinner
    Copy link
    Member

    My test included in mktime_fix_and_tests.patch has a problem: the
    timezone is constant and it's mine (GMT+1). I don't know how to write
    a generic test working on any time zone. I can't use
    datetime.fromtimestamp() because datetime.fromtimestamp() uses
    time.mktime() :-)

    @vstinner
    Copy link
    Member

    New version of my fix:

    • the test doesn't depend on _my_ local anymore: it uses localtime()
      to get the time tuple in the host local
    • ignore the test if mktime(-2) raise an OverflowError: avoid the
      test on Windows

    Is it now ok for everyone?

    @amauryfa
    Copy link
    Member

    Is the "break" intended in the test function? it seems that this will
    skip the whole test. Isn't "continue" better?

    @vstinner
    Copy link
    Member

    @Amaury: You wrote:

    << But negative time_t are still not allowed by the Microsoft CRT,
    the tests fail.>>

    So I choosed to skip mktime(-1) test if mktime(-2) fails.

    I don't have Windows to test my patch nor current behaviour.

    @AlexanderBelopolsky
    Copy link
    Mannequin

    AlexanderBelopolsky mannequin commented Feb 18, 2010

    Victor,

    With bpo-2736, you included a variant of this patch where you use -1 as a sentinel value for tm_wday. I think this is a better choice. (The answer to the ultimate question of life is not universally known.:-)

    On a more serious note, is checking for the -1 return value necessary? I would think a check for changed tm_wday would be enough.

    Finally, a coding style nitpick: don't use superfluous parenthesis in logical expressions.

    @AlexanderBelopolsky
    Copy link
    Mannequin

    AlexanderBelopolsky mannequin commented Feb 18, 2010

    I wonder: with year bounds being checked in gettmarg() and mktime accepting arbitrary values for the rest of the tm structure members (at least it appears to on my Mac), is it possible trigger "mktime argument out of range"?

    If it is possible, then a unit test should be added for such case. Note that the bpo-2736 patch contains a typo that assures that overflow is never reported, but the unit test presented here does not catch that bug:

    """
    +	buf.tm_wday = -1;
     	tt = mktime(&buf);
    -	if (tt == (time_t)(-1)) {
    +	if (tt == (time_t)(-1) && buf.tm_wday == 1) {
     		PyErr_SetString(PyExc_OverflowError,
     				"mktime argument out of range");
    """
    (Note missing '-' in buf.tm_wday == 1 check. See issue2736.)

    @abalkin abalkin self-assigned this Jun 6, 2010
    @abalkin
    Copy link
    Member

    abalkin commented Jun 17, 2010

    Is this important enough to try to get in 2.7 before rc2? Victor?

    @abalkin abalkin added extension-modules C modules in the Modules dir type-bug An unexpected behavior, bug, or error labels Jun 17, 2010
    @vstinner
    Copy link
    Member

    Is this important enough to try to get in 2.7 before rc2?

    I prefer to not include this patch in 2.7. I don't think that many people have this problem and it can be fixed later. It's too late for 2.7. Should it be fixed in 2.7.1 or only in 3.2 (and maybe in 3.1)?

    @abalkin
    Copy link
    Member

    abalkin commented Jan 11, 2011

    Committed in revision 87919. If bots are happy about the unit test, this should be backported to 3.1 and 2.7.

    @abalkin
    Copy link
    Member

    abalkin commented Feb 16, 2011

    Backported in r88425 (3.1) and r88427 (2.7).

    @abalkin abalkin closed this as completed Feb 16, 2011
    @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
    extension-modules C modules in the Modules dir type-bug An unexpected behavior, bug, or error
    Projects
    None yet
    Development

    No branches or pull requests

    3 participants