# HG changeset patch # User Paul Eggert # Date 1143232824 0 # Node ID 55e66496ae1a48feb3b231424db358e08b7e0433 # Parent 68644cbc6a004a1072273ea889adb3b84ba3ca42 * editfns.c: (TM_YEAR_BASE): Move up. (Fdecode_time, Fencode_time): Use TM_YEAR_BASE instead of 1900. (Fdecode_time): Cast tm_year to EMACS_INT, to avoid overflow when int is narrower than EMACS_INT. (Fcurrent_time_string): As with Fformat_time_string, report an invalid time specification if the argument is invalid. Also, check for out-of-range time stamps. diff -r 68644cbc6a00 -r 55e66496ae1a src/ChangeLog --- a/src/ChangeLog Fri Mar 24 15:24:20 2006 +0000 +++ b/src/ChangeLog Fri Mar 24 20:40:24 2006 +0000 @@ -1,3 +1,23 @@ +2006-03-24 Paul Eggert + + * editfns.c: Do not use ctime, since it has undefined behavior + with out-of-range time stamps. This fixes a bug where + (current-time-string '(2814749767106 0)) would make Emacs dump + core on 64-bit Solaris 8. The fix is to use localtime+asctime + (checking for in-range results) instead of ctime. Please see + + for more details about this portability problem. + (TM_YEAR_BASE): Move up, so the changes below can use it. + (Fdecode_time, Fencode_time): Use TM_YEAR_BASE instead of 1900. + (Fdecode_time): Cast tm_year to EMACS_INT, to avoid overflow when + int is narrower than EMACS_INT. + (Fcurrent_time_string): As with Fformat_time_string, report an + invalid time specification if the argument is invalid. Also, + check for out-of-range time stamps; this prevents a buffer overrun + that causes Emacs to dump core on 64-bit Solaris sparc, and it + preserves the historic behavior of always returning a fixed-size + string. + 2006-03-24 Kim F. Storm * xterm.c (handle_one_xevent): diff -r 68644cbc6a00 -r 55e66496ae1a src/editfns.c --- a/src/editfns.c Fri Mar 24 15:24:20 2006 +0000 +++ b/src/editfns.c Fri Mar 24 20:40:24 2006 +0000 @@ -72,6 +72,8 @@ extern char **environ; #endif +#define TM_YEAR_BASE 1900 + extern size_t emacs_strftimeu P_ ((char *, size_t, const char *, const struct tm *, int)); static int tm_diff P_ ((struct tm *, struct tm *)); @@ -721,7 +723,7 @@ int orig_point = 0; int fwd; Lisp_Object prev_old, prev_new; - + if (NILP (new_pos)) /* Use the current point, and afterwards, set it. */ { @@ -736,7 +738,7 @@ prev_old = make_number (XFASTINT (old_pos) - 1); prev_new = make_number (XFASTINT (new_pos) - 1); - + if (NILP (Vinhibit_field_text_motion) && !EQ (new_pos, old_pos) && (!NILP (Fget_char_property (new_pos, Qfield, Qnil)) @@ -1722,7 +1724,7 @@ XSETFASTINT (list_args[2], decoded_time->tm_hour); XSETFASTINT (list_args[3], decoded_time->tm_mday); XSETFASTINT (list_args[4], decoded_time->tm_mon + 1); - XSETINT (list_args[5], decoded_time->tm_year + 1900); + XSETINT (list_args[5], TM_YEAR_BASE + (EMACS_INT) decoded_time->tm_year); XSETFASTINT (list_args[6], decoded_time->tm_wday); list_args[7] = (decoded_time->tm_isdst)? Qt : Qnil; @@ -1778,7 +1780,7 @@ tm.tm_hour = XINT (args[2]); tm.tm_mday = XINT (args[3]); tm.tm_mon = XINT (args[4]) - 1; - tm.tm_year = XINT (args[5]) - 1900; + tm.tm_year = XINT (args[5]) - TM_YEAR_BASE; tm.tm_isdst = -1; if (CONSP (zone)) @@ -1844,11 +1846,16 @@ { time_t value; char buf[30]; + struct tm *tm; register char *tem; if (! lisp_time_argument (specified_time, &value, NULL)) - value = -1; - tem = (char *) ctime (&value); + error ("Invalid time specification"); + tm = localtime (&value); + if (! (tm && -999 - TM_YEAR_BASE <= tm->tm_year + && tm->tm_year <= 9999 - TM_YEAR_BASE)) + error ("Specified time is not representable"); + tem = asctime (tm); strncpy (buf, tem, 24); buf[24] = 0; @@ -1856,8 +1863,6 @@ return build_string (buf); } -#define TM_YEAR_BASE 1900 - /* Yield A - B, measured in seconds. This function is copied from the GNU C Library. */ static int