summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwtc%google.com <devnull@localhost>2009-03-24 22:58:57 +0000
committerwtc%google.com <devnull@localhost>2009-03-24 22:58:57 +0000
commit852e6fb58ea6769594d6ab7168f75299103ddadc (patch)
tree5339983d6c86b061828007be7c61812ec2ad3f22
parenta0ddfd5a29993455dd190fdac8a097382980409d (diff)
downloadnspr-hg-852e6fb58ea6769594d6ab7168f75299103ddadc.tar.gz
Bug 480740: When Visual C++ 2005 is used, don't call mktime when we know
the input date would cause mktime to call the invalid parameter handler. r=nelson. Modified Files: Tag: NSPR_4_7_BRANCH pr/src/misc/prtime.c pr/tests/Makefile.in pr/tests/runtests.pl pr/tests/runtests.sh Added Files: Tag: NSPR_4_7_BRANCH pr/tests/parsetm.c
-rw-r--r--pr/src/misc/prtime.c39
-rw-r--r--pr/tests/Makefile.in1
-rw-r--r--pr/tests/parsetm.c116
-rwxr-xr-xpr/tests/runtests.pl1
-rwxr-xr-xpr/tests/runtests.sh1
5 files changed, 151 insertions, 7 deletions
diff --git a/pr/src/misc/prtime.c b/pr/src/misc/prtime.c
index 5f05d5ef..42ab815b 100644
--- a/pr/src/misc/prtime.c
+++ b/pr/src/misc/prtime.c
@@ -50,10 +50,8 @@
#include <string.h>
#include <ctype.h>
-
-#ifdef XP_MAC
+#include <errno.h> /* for EINVAL */
#include <time.h>
-#endif
/*
* The COUNT_LEAPS macro counts the number of leap years passed by
@@ -519,8 +517,6 @@ PR_NormalizeTime(PRExplodedTime *time, PRTimeParamFn params)
*-------------------------------------------------------------------------
*/
-#include <time.h>
-
#if defined(HAVE_INT_LOCALTIME_R)
/*
@@ -1573,6 +1569,12 @@ PR_ParseTimeStringToExplodedTime(
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)
{
@@ -1622,7 +1624,32 @@ PR_ParseTimeStringToExplodedTime(
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;
@@ -1644,8 +1671,6 @@ PR_ParseTimeStringToExplodedTime(
+ 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;
diff --git a/pr/tests/Makefile.in b/pr/tests/Makefile.in
index c55acf23..d1bbc011 100644
--- a/pr/tests/Makefile.in
+++ b/pr/tests/Makefile.in
@@ -125,6 +125,7 @@ CSRCS = \
op_nofil.c \
openfile.c \
parent.c \
+ parsetm.c \
peek.c \
perf.c \
pipeping.c \
diff --git a/pr/tests/parsetm.c b/pr/tests/parsetm.c
new file mode 100644
index 00000000..24148286
--- /dev/null
+++ b/pr/tests/parsetm.c
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * This test program should eventually become a full-blown test for
+ * PR_ParseTimeString. Right now it just verifies that PR_ParseTimeString
+ * doesn't crash on an out-of-range time string (bug 480740).
+ */
+
+#include "prtime.h"
+
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+PRBool debug_mode = PR_TRUE;
+
+static char *dayOfWeek[] =
+ { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "???" };
+static char *month[] =
+ { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "???" };
+
+static void PrintExplodedTime(const PRExplodedTime *et) {
+ PRInt32 totalOffset;
+ PRInt32 hourOffset, minOffset;
+ const char *sign;
+
+ /* Print day of the week, month, day, hour, minute, and second */
+ if (debug_mode) printf("%s %s %ld %02ld:%02ld:%02ld ",
+ dayOfWeek[et->tm_wday], month[et->tm_month], et->tm_mday,
+ et->tm_hour, et->tm_min, et->tm_sec);
+
+ /* Print time zone */
+ totalOffset = et->tm_params.tp_gmt_offset + et->tm_params.tp_dst_offset;
+ if (totalOffset == 0) {
+ if (debug_mode) printf("UTC ");
+ } else {
+ sign = "+";
+ if (totalOffset < 0) {
+ totalOffset = -totalOffset;
+ sign = "-";
+ }
+ hourOffset = totalOffset / 3600;
+ minOffset = (totalOffset % 3600) / 60;
+ if (debug_mode)
+ printf("%s%02ld%02ld ", sign, hourOffset, minOffset);
+ }
+
+ /* Print year */
+ if (debug_mode) printf("%hd", et->tm_year);
+}
+
+int main(int argc, char **argv)
+{
+ PRTime ct;
+ PRExplodedTime et;
+ PRStatus rv;
+ char *sp1 = "Sat, 1 Jan 3001 00:00:00"; /* no time zone */
+ char *sp2 = "Fri, 31 Dec 3000 23:59:60"; /* no time zone, not normalized */
+
+#if _MSC_VER >= 1400
+ /* Run this test in the US Pacific Time timezone. */
+ _putenv_s("TZ", "PST8PDT");
+ _tzset();
+#endif
+
+ rv = PR_ParseTimeString(sp1, PR_FALSE, &ct);
+ printf("rv = %d\n", rv);
+ PR_ExplodeTime(ct, PR_GMTParameters, &et);
+ PrintExplodedTime(&et);
+ printf("\n");
+
+ rv = PR_ParseTimeString(sp2, PR_FALSE, &ct);
+ printf("rv = %d\n", rv);
+ PR_ExplodeTime(ct, PR_GMTParameters, &et);
+ PrintExplodedTime(&et);
+ printf("\n");
+
+ return 0;
+}
diff --git a/pr/tests/runtests.pl b/pr/tests/runtests.pl
index 08088877..912c6301 100755
--- a/pr/tests/runtests.pl
+++ b/pr/tests/runtests.pl
@@ -333,6 +333,7 @@ $prog = shift; # Program to test
"op_filok",
"op_nofil",
"parent",
+"parsetm",
"peek",
"perf",
"pipeping",
diff --git a/pr/tests/runtests.sh b/pr/tests/runtests.sh
index f9149481..a31b261e 100755
--- a/pr/tests/runtests.sh
+++ b/pr/tests/runtests.sh
@@ -161,6 +161,7 @@ op_filnf
op_filok
op_nofil
parent
+parsetm
peek
perf
pipeping