This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: datetime.datetime initialization needs more strict checking
Type: Stage:
Components: Library (Lib) Versions: Python 2.3
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: tim.peters Nosy List: dubnerm, gvanrossum, tim.peters
Priority: high Keywords:

Created on 2003-11-22 02:19 by dubnerm, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Messages (8)
msg19078 - (view) Author: Michael Dubner (dubnerm) Date: 2003-11-22 02:19
Friend of mine wrote following program:
---------------------------------
import datetime
t=datetime.datetime('1995-03-25')
print t.ctime()
---------------------------------
This is obviously wrong code, but instead of reporting
this at second line python crashes on third line (with
ctime).

Info:
Using Python 2.3.2 on Windows 2000
msg19079 - (view) Author: Tim Peters (tim.peters) * (Python committer) Date: 2003-11-22 03:16
Logged In: YES 
user_id=31435

LOL!  Assigned to Guido for his amusement.  One string 
argument of exactly size 10 triggers the "secret" backdoor to 
construct a datetime.datetime from a pickle.  The datetime 
constructed here is insane, and provokes Microsoft's library 
into crashing.  In a debug build, it triggers an assertion error 
in the datetime module:

>>> import datetime
[16122 refs]
>>> datetime.datetime('1995-03-25')
datetime.datetime(12601, 57, 53, 45, 48, 51, 2961973)
[16124 refs]
>>> _.ctime()
Assertion failed: month <= 12, file 
C:\Code\python\Modules\datetimemodule.c, line 189

Boosted priority since it's a way to crash the interpreter on 
Windows.
msg19080 - (view) Author: Michael Dubner (dubnerm) Date: 2003-11-24 01:36
Logged In: YES 
user_id=39274

Of cause i've seen that backdoor, but from my point of view
constructor is not so time-critical that insertion of sanity
chechs will slow down in most (sane) scenarios.
msg19081 - (view) Author: Tim Peters (tim.peters) * (Python committer) Date: 2003-11-24 23:50
Logged In: YES 
user_id=31435

Na, it's not that simple.  Blazing-fast pickling and unpickling 
was a design goal for datetime.  "Sanity checks" require two-
tailed comparisons on 7 distinct fields, and checking of the 
day field requires month-specific comparison, and may even 
require determing whether it's a leap year.  Doing all that 
would make sucking datetimes out of pickles enormously 
slower than it is now (it's merely a 10-byte string copy now).

If we were willing to do all the checks we do on things coming 
through the front door, we wouldn't call it a back door <wink>.

OTOH, we shouldn't allow a hostile user the ability to crash 
the system via constructing a damaged datetime pickle 
either, so maybe the whole "fast back door" idea is impossible 
to rehabilitate.
msg19082 - (view) Author: Michael Dubner (dubnerm) Date: 2003-11-25 01:17
Logged In: YES 
user_id=39274

Can we add dummy fields to change size of backdoor string so
it will not be same as commonly used formats?
msg19083 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2004-03-20 22:52
Logged In: YES 
user_id=6380

Not sure why this is assigned to me.

One suggestion: we could do a superficial check that would
catch the above honest mistake without claiming to prevent
all malicious attacks -- malicious pickles aren't something
we try to defend against in general (alas).
msg19084 - (view) Author: Tim Peters (tim.peters) * (Python committer) Date: 2004-03-21 20:53
Logged In: YES 
user_id=31435

Guido, it was assigned to you for (as the comment said) your 
amusement -- we asked each other the odds of anyone 
passing a string here when the backdoor was invented, and 
both thought "na".

What kind of superficial check did you have in mind here?  
The datetime object constructed is insane in 4 of its 7 fields, 
and I have no idea exactly which of those crashes MS's 
library:

>>> import datetime
>>> datetime.datetime('1995-03-25')
datetime.datetime(12601, 57, 53, 45, 48, 51, 2961973)
>>>

Oddly enough, it doesn't appear that the out-of-range year, 
day or microseconds are the problem; forcing the month alone 
into range stops the crash on Windows:

>>> datetime.datetime('19\x0c5-03-25')
datetime.datetime(12601, 12, 53, 45, 48, 51, 2961973)
>>> _.ctime()
'Fri Dec 53 45:48:51 12601'
>>>

So, ya, I could check the month alone, and that would 
prevent this particular crash under MSVC 6.  But there's 
simply no guessing whether other platforms can tolerate the 
insanity remaining, whether this is the only case Windows 
can't tolerate, or whether the kind of crazy datetime object 
constructed just above (which would pass a months-only 
check) could still be used to crash the interpreter after it's 
constructed (the datetime code assumes objects aren't 
insane).


dubnerm:  It's too late to add "dummy fields".  If we did, 
datetime pickles wouldn't be readable across Python releases.

It's unlikely that any by-hand typed string would have a valid 
pickle code for a month in the third byte, so I guess I'll settle 
for that.
msg19085 - (view) Author: Tim Peters (tim.peters) * (Python committer) Date: 2004-03-21 23:49
Logged In: YES 
user_id=31435

I added the month sanity check to the date() and datetime() 
constructors.  The original example (or any "like it") raises 
TypeError now.

Lib/test/test_datetime.py; new revision: 1.46
Modules/datetimemodule.c; new revision: 1.71
History
Date User Action Args
2022-04-11 14:56:01adminsetgithub: 39583
2003-11-22 02:19:23dubnermcreate