diff options
author | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-03 01:24:01 +0000 |
---|---|---|
committer | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-03 01:24:01 +0000 |
commit | 1e031a19d6c759a0bbb21cdcb26f099d009d8924 (patch) | |
tree | 99b79f5b3fc301be050c65b4bb8ccbaf7adc37b9 /base | |
parent | dbf476de0ef1cdcc11c5f2d689b8755809a857fb (diff) | |
download | chromium_src-1e031a19d6c759a0bbb21cdcb26f099d009d8924.zip chromium_src-1e031a19d6c759a0bbb21cdcb26f099d009d8924.tar.gz chromium_src-1e031a19d6c759a0bbb21cdcb26f099d009d8924.tar.bz2 |
Avoid a crash in mktime() when Visual C++ 2005 is
used and the input date is in year 3001.
R=eroman
BUG=4387
Review URL: http://codereview.chromium.org/28340
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@10768 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r-- | base/pr_time_unittest.cc | 35 | ||||
-rw-r--r-- | base/third_party/nspr/prtime.cc | 36 |
2 files changed, 65 insertions, 6 deletions
diff --git a/base/pr_time_unittest.cc b/base/pr_time_unittest.cc index 3b096a2..2ebc724 100644 --- a/base/pr_time_unittest.cc +++ b/base/pr_time_unittest.cc @@ -136,7 +136,7 @@ TEST_F(PRTimeTest, ParseTimeTest9) { // This tests the Time::FromString wrapper over PR_ParseTimeString TEST_F(PRTimeTest, ParseTimeTest10) { Time parsed_time; - bool result = Time::FromString(L"15/10/07 12:45",&parsed_time); + bool result = Time::FromString(L"15/10/07 12:45", &parsed_time); EXPECT_EQ(true, result); time_t computed_time = parsed_time.ToTimeT(); @@ -172,7 +172,7 @@ TEST_F(PRTimeTest, ParseTimeTestEpoch0) { TEST_F(PRTimeTest, ParseTimeTestEpoch1) { Time parsed_time; - + // time_t == 1 second after epoch == 1 EXPECT_EQ(true, Time::FromString(L"Thu Jan 01 01:00:01 +0100 1970", &parsed_time)); @@ -184,7 +184,7 @@ TEST_F(PRTimeTest, ParseTimeTestEpoch1) { TEST_F(PRTimeTest, ParseTimeTestEpoch2) { Time parsed_time; - + // time_t == 2 seconds after epoch == 2 EXPECT_EQ(true, Time::FromString(L"Thu Jan 01 01:00:02 +0100 1970", &parsed_time)); @@ -238,4 +238,33 @@ TEST_F(PRTimeTest, ParseTimeTestEmpty) { EXPECT_FALSE(Time::FromString(L"", &parsed_time)); } +// This test should not crash when compiled with Visual C++ 2005 (see +// http://crbug.com/4387). +TEST_F(PRTimeTest, ParseTimeTestOutOfRange) { + PRTime parsed_time = 0; + // Note the lack of timezone in the time string. The year has to be 3001. + // The date has to be after 23:59:59, December 31, 3000, US Pacific Time, so + // we use January 2, 3001 to make sure it's after the magic maximum in any + // timezone. + PRStatus result = PR_ParseTimeString("Sun Jan 2 00:00:00 3001", + PR_FALSE, &parsed_time); + EXPECT_EQ(PR_SUCCESS, result); +} + +TEST_F(PRTimeTest, ParseTimeTestNotNormalized1) { + PRTime parsed_time = 0; + PRStatus result = PR_ParseTimeString("Mon Oct 15 12:44:60 PDT 2007", + PR_FALSE, &parsed_time); + EXPECT_EQ(PR_SUCCESS, result); + EXPECT_EQ(comparison_time_pdt, parsed_time); +} + +TEST_F(PRTimeTest, ParseTimeTestNotNormalized2) { + PRTime parsed_time = 0; + PRStatus result = PR_ParseTimeString("Sun Oct 14 36:45 PDT 2007", + PR_FALSE, &parsed_time); + EXPECT_EQ(PR_SUCCESS, result); + EXPECT_EQ(comparison_time_pdt, parsed_time); +} + } // namespace diff --git a/base/third_party/nspr/prtime.cc b/base/third_party/nspr/prtime.cc index cff5048..733db58 100644 --- a/base/third_party/nspr/prtime.cc +++ b/base/third_party/nspr/prtime.cc @@ -41,7 +41,7 @@ * * NSPR date and time functions * - * CVS revision 3.36 + * CVS revision 3.37 */ /* @@ -71,6 +71,7 @@ #elif defined(OS_MACOSX) #include <CoreFoundation/CoreFoundation.h> #endif +#include <errno.h> /* for EINVAL */ #include <time.h> /* Implements the Unix localtime_r() function for windows */ @@ -1092,6 +1093,12 @@ PR_ParseTimeString( result->tm_year = year; if (dotw != TT_UNKNOWN) result->tm_wday = (((int)dotw) - ((int)TT_SUN)); + /* + * Mainly to compute wday and yday, but normalized time is also required + * by the check below that works around a Visual C++ 2005 mktime problem. + */ + PR_NormalizeTime(result, PR_GMTParameters); + /* The remaining work is to set the gmt and dst offsets in tm_params. */ if (zone == TT_UNKNOWN && default_to_gmt) { @@ -1141,7 +1148,32 @@ PR_ParseTimeString( date you are handing it is in daylight savings mode or not; and if you're wrong, it will "fix" it for you. */ localTime.tm_isdst = -1; + +#if _MSC_VER >= 1400 /* 1400 = Visual C++ 2005 (8.0) */ + /* + * mktime will return (time_t) -1 if the input is a date + * after 23:59:59, December 31, 3000, US Pacific Time (not + * UTC as documented): + * http://msdn.microsoft.com/en-us/library/d1y53h2a(VS.80).aspx + * But if the year is 3001, mktime also invokes the invalid + * parameter handler, causing the application to crash. This + * problem has been reported in + * http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=266036. + * We avoid this crash by not calling mktime if the date is + * out of range. To use a simple test that works in any time + * zone, we consider year 3000 out of range as well. (See + * bug 480740.) + */ + if (result->tm_year >= 3000) { + /* Emulate what mktime would have done. */ + errno = EINVAL; + secs = (time_t) -1; + } else { + secs = mktime(&localTime); + } +#else secs = mktime(&localTime); +#endif if (secs != (time_t) -1) { PRTime usecs64; @@ -1163,8 +1195,6 @@ PR_ParseTimeString( + 1440 * (localTime.tm_mday - 2); } - /* mainly to compute wday and yday */ - PR_NormalizeTime(result, PR_GMTParameters); result->tm_params.tp_gmt_offset = zone_offset * 60; result->tm_params.tp_dst_offset = dst_offset * 60; |