time.mktime memory access violation bug

Discussion in 'Python' started by Bengt Richter, Nov 18, 2003.

  1. Python 2.3.2 (#49, Oct 2 2003, 20:02:00) [MSC v.1200 32 bit (Intel)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import time
    >>> time.mktime((1969, 12, 31, 17, 0, 0, 0, 0, 0))

    3600.0
    >>> time.mktime((1969, 12, 31, 17, 0, 0, 0, 0, 1))

    0.0
    >>> time.mktime((1969, 12, 31, 16, 0, 0, 0, 0, 1))

    [crash with popup]


    I got:

    The instruction at "0x7802a7ff" referenced memory at "0x00000000". The memory
    could not be "read".

    I would have hoped for an informative ValueError exception.

    This is on NT4. My local time zone is PST.

    If I let the MSVC++6 debugger try to chase it, it says
    Unhandled exception in python.exe (MSVCRT.DLL): 0xC0000005: Access Violation

    and fwiw without source it's pointing to the rep movs in this context:

    7802A7F1 call 7802A4BF
    7802A7F6 pop ecx
    7802A7F7 push 9
    7802A7F9 mov esi,eax
    7802A7FB mov eax,dword ptr [ebp+8]
    7802A7FE pop ecx
    7802A7FF rep movs dword ptr [edi],dword ptr [esi]
    7802A801 pop edi
    7802A802 pop esi
    7802A803 pop ebp
    7802A804 ret
    7802A805 test ecx,ecx


    and esi is zero, so I guess that did it.

    Someone have a debug version to check this out?

    Regards,
    Bengt Richter
    Bengt Richter, Nov 18, 2003
    #1
    1. Advertising

  2. Bengt Richter wrote:
    > Python 2.3.2 (#49, Oct 2 2003, 20:02:00) [MSC v.1200 32 bit (Intel)] on win32
    > Type "help", "copyright", "credits" or "license" for more information.
    > >>> import time
    > >>> time.mktime((1969, 12, 31, 17, 0, 0, 0, 0, 0))

    > 3600.0
    > >>> time.mktime((1969, 12, 31, 17, 0, 0, 0, 0, 1))

    > 0.0
    > >>> time.mktime((1969, 12, 31, 16, 0, 0, 0, 0, 1))

    > [crash with popup]


    Curious. I get (windows XP):

    Python 2.3.2 (#49, Oct 2 2003, 20:02:00) [MSC v.1200 32 bit (Intel)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import time
    >>> time.mktime((1969, 12, 31, 17, 0, 0, 0, 0, 0))

    Traceback (most recent call last):
    File "<stdin>", line 1, in ?
    OverflowError: mktime argument out of range
    >>> time.mktime((1969, 12, 31, 17, 0, 0, 0, 0, 1))

    Traceback (most recent call last):
    File "<stdin>", line 1, in ?
    OverflowError: mktime argument out of range
    >>> time.mktime((1969, 12, 31, 16, 0, 0, 0, 0, 1))

    Traceback (most recent call last):
    File "<stdin>", line 1, in ?
    OverflowError: mktime argument out of range
    >>>


    On Linux I get the same results. Something fishy is going
    on with your Python...

    --Irmen de Jong
    Irmen de Jong, Nov 19, 2003
    #2
    1. Advertising

  3. On Wed, 19 Nov 2003 02:10:36 +0100, Irmen de Jong <> wrote:

    >Bengt Richter wrote:
    >> Python 2.3.2 (#49, Oct 2 2003, 20:02:00) [MSC v.1200 32 bit (Intel)] on win32
    >> Type "help", "copyright", "credits" or "license" for more information.
    >> >>> import time
    >> >>> time.mktime((1969, 12, 31, 17, 0, 0, 0, 0, 0))

    >> 3600.0
    >> >>> time.mktime((1969, 12, 31, 17, 0, 0, 0, 0, 1))

    >> 0.0
    >> >>> time.mktime((1969, 12, 31, 16, 0, 0, 0, 0, 1))

    >> [crash with popup]

    >
    >Curious. I get (windows XP):
    >
    >Python 2.3.2 (#49, Oct 2 2003, 20:02:00) [MSC v.1200 32 bit (Intel)] on win32
    >Type "help", "copyright", "credits" or "license" for more information.
    > >>> import time
    > >>> time.mktime((1969, 12, 31, 17, 0, 0, 0, 0, 0))

    >Traceback (most recent call last):
    > File "<stdin>", line 1, in ?
    >OverflowError: mktime argument out of range
    > >>> time.mktime((1969, 12, 31, 17, 0, 0, 0, 0, 1))

    >Traceback (most recent call last):
    > File "<stdin>", line 1, in ?
    >OverflowError: mktime argument out of range
    > >>> time.mktime((1969, 12, 31, 16, 0, 0, 0, 0, 1))

    >Traceback (most recent call last):
    > File "<stdin>", line 1, in ?
    >OverflowError: mktime argument out of range
    > >>>

    >
    >On Linux I get the same results. Something fishy is going
    >on with your Python...
    >

    Well, you're in a different time zone. I think you have to compensate for
    that in setting up the equivalent of zero time epoch. Then hit that with dst=1.
    Or there could be something fishy ;-)

    Regards,
    Bengt Richter
    Bengt Richter, Nov 19, 2003
    #3
  4. Bengt Richter

    Peter Otten Guest

    Bengt Richter wrote:

    > Python 2.3.2 (#49, Oct 2 2003, 20:02:00) [MSC v.1200 32 bit (Intel)] on
    > win32 Type "help", "copyright", "credits" or "license" for more
    > information.
    > >>> import time
    > >>> time.mktime((1969, 12, 31, 17, 0, 0, 0, 0, 0))

    > 3600.0
    > >>> time.mktime((1969, 12, 31, 17, 0, 0, 0, 0, 1))

    > 0.0
    > >>> time.mktime((1969, 12, 31, 16, 0, 0, 0, 0, 1))

    > [crash with popup]


    More data points:

    import time
    n = 1000000
    for i in range(-n, n):
    lt = time.localtime(i)
    try:
    time.mktime(lt)
    except OverflowError:
    print "Cannot cope with %r %r" % (i, lt)

    Python 2.3.2 (#1, Oct 21 2003, 10:03:19)
    [GCC 3.2] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import check_mktime

    Cannot cope with -1 (1970, 1, 1, 0, 59, 59, 3, 1, 0)
    >>>


    Now omitting localtime():

    >>> time.mktime((1970, 1, 1, 0, 59, 59, 3, 1, 0))

    Traceback (most recent call last):
    File "<stdin>", line 1, in ?
    OverflowError: mktime argument out of range
    >>>


    So, on Linux:

    - times < 0 seem to be OK.
    - but -1 is used (abused?) as an error value

    Attempts to provoke an OverflowError with the above technique for the lower
    limit failed due to the following behaviour of localtime():

    >>> time.localtime(-3600*24*365*80)

    (1901, 12, 13, 21, 45, 52, 4, 347, 0)

    I. e. always the same for low values, so, "guessing" the lower limit:

    >>> time.localtime(-2**31)

    (1901, 12, 13, 21, 45, 52, 4, 347, 0)
    >>> time.localtime(-2**31+1)

    (1901, 12, 13, 21, 45, 53, 4, 347, 0)
    >>> time.localtime(-2**31+2)

    (1901, 12, 13, 21, 45, 54, 4, 347, 0)
    >>>


    But mktime() seems OK:

    >>> time.mktime((1901, 12, 13, 21, 45, 51, 4, 347, 0))

    Traceback (most recent call last):
    File "<stdin>", line 1, in ?
    OverflowError: mktime argument out of range
    >>>


    Conclusion: The fatal error is probably due to NT's mktime() implementation.
    Times before (1901, ...) should raise an Overflow error. I don't like the
    -1 special value, but I am not sure how the error value of the underlying C
    library and one second before the Unix epoch could be disambiguated.

    Peter
    Peter Otten, Nov 20, 2003
    #4
  5. On Thu, 20 Nov 2003 21:01:18 +0100, Peter Otten <> wrote:

    >Bengt Richter wrote:
    >
    >> Python 2.3.2 (#49, Oct 2 2003, 20:02:00) [MSC v.1200 32 bit (Intel)] on
    >> win32 Type "help", "copyright", "credits" or "license" for more
    >> information.
    >> >>> import time
    >> >>> time.mktime((1969, 12, 31, 17, 0, 0, 0, 0, 0))

    >> 3600.0
    >> >>> time.mktime((1969, 12, 31, 17, 0, 0, 0, 0, 1))

    >> 0.0
    >> >>> time.mktime((1969, 12, 31, 16, 0, 0, 0, 0, 1))

    >> [crash with popup]

    >
    >More data points:
    >
    >import time
    >n = 1000000
    >for i in range(-n, n):
    > lt = time.localtime(i)
    > try:
    > time.mktime(lt)
    > except OverflowError:
    > print "Cannot cope with %r %r" % (i, lt)
    >
    >Python 2.3.2 (#1, Oct 21 2003, 10:03:19)
    >[GCC 3.2] on linux2
    >Type "help", "copyright", "credits" or "license" for more information.
    >>>> import check_mktime

    >Cannot cope with -1 (1970, 1, 1, 0, 59, 59, 3, 1, 0)
    >>>>

    >
    >Now omitting localtime():
    >
    >>>> time.mktime((1970, 1, 1, 0, 59, 59, 3, 1, 0))

    >Traceback (most recent call last):
    > File "<stdin>", line 1, in ?
    >OverflowError: mktime argument out of range
    >>>>

    >
    >So, on Linux:
    >
    >- times < 0 seem to be OK.
    >- but -1 is used (abused?) as an error value
    >
    >Attempts to provoke an OverflowError with the above technique for the lower
    >limit failed due to the following behaviour of localtime():
    >
    >>>> time.localtime(-3600*24*365*80)

    >(1901, 12, 13, 21, 45, 52, 4, 347, 0)
    >
    >I. e. always the same for low values, so, "guessing" the lower limit:
    >
    >>>> time.localtime(-2**31)

    >(1901, 12, 13, 21, 45, 52, 4, 347, 0)
    >>>> time.localtime(-2**31+1)

    >(1901, 12, 13, 21, 45, 53, 4, 347, 0)
    >>>> time.localtime(-2**31+2)

    >(1901, 12, 13, 21, 45, 54, 4, 347, 0)
    >>>>

    >
    >But mktime() seems OK:
    >
    >>>> time.mktime((1901, 12, 13, 21, 45, 51, 4, 347, 0))

    >Traceback (most recent call last):
    > File "<stdin>", line 1, in ?
    >OverflowError: mktime argument out of range
    >>>>

    >
    >Conclusion: The fatal error is probably due to NT's mktime() implementation.
    >Times before (1901, ...) should raise an Overflow error. I don't like the
    >-1 special value, but I am not sure how the error value of the underlying C
    >library and one second before the Unix epoch could be disambiguated.
    >

    What does the following sequence do on your machine? Your tests did not apparently
    exercise the daylight savings time path involved in my crash. E.g.,

    >>> import time
    >>> time.localtime(0)

    (1969, 12, 31, 16, 0, 0, 2, 365, 0)
    >>> time.mktime(time.localtime(0))

    0.0
    >>> time.mktime(time.localtime(0)[:6]+(0,0,1))


    (my NT4 crashes here)

    BTW, I wonder if mktime does anything with those zeroes that I supplied at [6:8]
    Hm, well,
    >>> time.mktime(time.localtime(0)[:-1]+(1,))

    crashes too, so probably that's not involved.

    No time to pursue this in the code, sorry ...

    Regards,
    Bengt Richter
    Bengt Richter, Nov 20, 2003
    #5
  6. Bengt Richter

    Peter Otten Guest

    Bengt Richter wrote:

    > What does the following sequence do on your machine? Your tests did not
    > apparently exercise the daylight savings time path involved in my crash.


    My (tacit, sorry) assumption was that setting daylight savings to 1 would
    subtract 3600s from the Unix epoch, making it a negative value and thus
    provoke the crash. But that was wrong:

    >>> def d(t):

    .... tpl = time.localtime(t)
    .... return time.mktime(tpl[:-3] + (0, 0, 0)) - time.mktime(tpl[:-3] +
    (0, 0, 1))
    ....
    >>> d(0)

    0.0

    With an arbitrary summer time:

    >>> d(962924461)

    3600.0
    >>>


    > E.g.,
    >
    > >>> import time
    > >>> time.localtime(0)

    > (1969, 12, 31, 16, 0, 0, 2, 365, 0)
    > >>> time.mktime(time.localtime(0))

    > 0.0
    > >>> time.mktime(time.localtime(0)[:6]+(0,0,1))

    >
    > (my NT4 crashes here)
    >


    For completeness:

    >>> time.localtime(0)

    (1970, 1, 1, 1, 0, 0, 3, 1, 0)
    >>> time.mktime(time.localtime(0))

    0.0
    >>> time.mktime(time.localtime(0)[:6] + (0, 0, 1))

    0.0
    >>>


    From the docs I would expect that such a "smart" behaviour would require a
    DST flag of -1.

    Looking at the two zero times (UTC + x vs UTC - x hours) I wonder if an NT
    machine on this side of the zero meridian would encounter the same
    problems.

    Peter
    Peter Otten, Nov 20, 2003
    #6
  7. On Thu, 20 Nov 2003 23:54:24 +0100, Peter Otten <> wrote:

    >Bengt Richter wrote:
    >
    >> What does the following sequence do on your machine? Your tests did not
    >> apparently exercise the daylight savings time path involved in my crash.

    >
    >My (tacit, sorry) assumption was that setting daylight savings to 1 would
    >subtract 3600s from the Unix epoch, making it a negative value and thus
    >provoke the crash. But that was wrong:
    >
    >>>> def d(t):

    >... tpl = time.localtime(t)
    >... return time.mktime(tpl[:-3] + (0, 0, 0)) - time.mktime(tpl[:-3] +
    >(0, 0, 1))
    >...
    >>>> d(0)

    >0.0
    >
    >With an arbitrary summer time:
    >
    >>>> d(962924461)

    >3600.0
    >>>>

    >
    >> E.g.,
    >>
    >> >>> import time
    >> >>> time.localtime(0)

    >> (1969, 12, 31, 16, 0, 0, 2, 365, 0)
    >> >>> time.mktime(time.localtime(0))

    >> 0.0
    >> >>> time.mktime(time.localtime(0)[:6]+(0,0,1))

    >>
    >> (my NT4 crashes here)
    >>

    >
    >For completeness:
    >
    >>>> time.localtime(0)

    >(1970, 1, 1, 1, 0, 0, 3, 1, 0)
    >>>> time.mktime(time.localtime(0))

    >0.0
    >>>> time.mktime(time.localtime(0)[:6] + (0, 0, 1))

    >0.0
    >>>>

    >
    >From the docs I would expect that such a "smart" behaviour would require a
    >DST flag of -1.

    Agreed.

    >
    >Looking at the two zero times (UTC + x vs UTC - x hours) I wonder if an NT
    >machine on this side of the zero meridian would encounter the same
    >problems.

    I suspect so. I think it is in the mktime.c of the MS library:
    >

    I suspect that "can't get NULL" is wrong in this snippet from D:\VC98\CRT\SRC\MKTIME.C
    when passed the zero epoch, because the associated localtime doesn't handle negative epoch time.

    ====

    /*
    * Convert this second count back into a time block structure.
    * If localtime returns NULL, return an error.
    */
    if ( (tbtemp = localtime(&tmptm1)) == NULL )
    goto err_mktime;

    /*
    * Now must compensate for DST. The ANSI rules are to use the
    * passed-in tm_isdst flag if it is non-negative. Otherwise,
    * compute if DST applies. Recall that tbtemp has the time without
    * DST compensation, but has set tm_isdst correctly.
    */
    if ( (tb->tm_isdst > 0) || ((tb->tm_isdst < 0) &&
    (tbtemp->tm_isdst > 0)) ) {
    tmptm1 += _dstbias;
    tbtemp = localtime(&tmptm1); /* reconvert, can't get NULL */
    }

    ====
    I think it dies a little later on
    *tb = *tbtemp;
    .... stepping through disassembly of optimized code with no source except the separate file
    to infer what is going on ;-/

    This is from MSVC++6.0 BTW, which UIAM windows python 2.3.2 still was compiled with(?)

    What is Python policy when a vendor lib module causes a bug?

    Regards,
    Bengt Richter
    Bengt Richter, Nov 21, 2003
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Kyle Teague
    Replies:
    3
    Views:
    655
    David White
    Nov 26, 2003
  2. McBooCzech

    time.mktime problem

    McBooCzech, Aug 30, 2005, in forum: Python
    Replies:
    4
    Views:
    867
    Edvard Majakari
    Sep 5, 2005
  3. KW
    Replies:
    1
    Views:
    1,808
    Eric Sosman
    Dec 8, 2004
  4. Alex
    Replies:
    5
    Views:
    472
    Jim Langston
    Sep 14, 2005
  5. saurabh

    time issue (mktime time_t tm)

    saurabh, Apr 14, 2009, in forum: C Programming
    Replies:
    3
    Views:
    1,848
Loading...

Share This Page