Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
emacs
emacs
Commits
d32df629
Commit
d32df629
authored
Mar 12, 2011
by
Paul Eggert
Browse files
Improve quality of tests for time stamp overflow.
parents
4248cca2
313c1e54
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
143 additions
and
37 deletions
+143
-37
src/ChangeLog
src/ChangeLog
+32
-0
src/deps.mk
src/deps.mk
+2
-1
src/dired.c
src/dired.c
+0
-7
src/editfns.c
src/editfns.c
+108
-25
src/systime.h
src/systime.h
+1
-4
No files found.
src/ChangeLog
View file @
d32df629
2011-03-13 Paul Eggert <eggert@cs.ucla.edu>
Improve quality of tests for time stamp overflow.
For example, without this patch (encode-time 0 0 0 1 1
1152921504606846976) returns the obviously-bogus value (-948597
62170) on my RHEL 5.5 x86-64 host. With the patch, it correctly
reports time overflow. See
<http://lists.gnu.org/archive/html/emacs-devel/2011-03/msg00470.html>.
* deps.mk (editfns.o): Depend on ../lib/intprops.h.
* editfns.c: Include limits.h and intprops.h.
(TIME_T_MIN, TIME_T_MAX): New macros.
(time_overflow): Move earlier, to before first use.
(hi_time, lo_time): New functions, for an accurate test for
out-of-range times.
(Fcurrent_time, Fget_internal_run_time, make_time): Use them.
(Fget_internal_run_time): Don't assume time_t fits in int.
(make_time): Use list2 instead of Fcons twice.
(Fdecode_time): More accurate test for out-of-range times.
(check_tm_member): New function.
(Fencode_time): Use it, to test for out-of-range times.
(lisp_time_argument): Don't rely on undefined left-shift and
right-shift behavior when checking for time stamp overflow.
* editfns.c (time_overflow): New function, refactoring common code.
(Fformat_time_string, Fdecode_time, Fencode_time):
(Fcurrent_time_string): Use it.
Move 'make_time' to be next to its inverse 'lisp_time_argument'.
* dired.c (make_time): Move to ...
* editfns.c (make_time): ... here.
* systime.h: Note the move.
2011-03-12 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
* fringe.c (update_window_fringes): Remove unused variables.
src/deps.mk
View file @
d32df629
...
...
@@ -87,7 +87,8 @@ dosfns.o: buffer.h termchar.h termhooks.h frame.h blockinput.h window.h \
msdos.h dosfns.h dispextern.h charset.h coding.h atimer.h systime.h
\
lisp.h $(config_h)
editfns.o
:
editfns.c window.h buffer.h systime.h $(INTERVALS_H) character.h
\
coding.h frame.h blockinput.h atimer.h ../lib/unistd.h ../lib/strftime.h
\
coding.h frame.h blockinput.h atimer.h
\
../lib/intprops.h ../lib/strftime.h ../lib/unistd.h
\
lisp.h globals.h $(config_h)
emacs.o
:
emacs.c commands.h systty.h syssignal.h blockinput.h process.h
\
termhooks.h buffer.h atimer.h systime.h $(INTERVALS_H) lisp.h $(config_h)
\
...
...
src/dired.c
View file @
d32df629
...
...
@@ -848,13 +848,6 @@ file_name_completion_stat (Lisp_Object dirname, DIRENTRY *dp, struct stat *st_ad
return
value
;
}
Lisp_Object
make_time
(
time_t
time
)
{
return
Fcons
(
make_number
(
time
>>
16
),
Fcons
(
make_number
(
time
&
0177777
),
Qnil
));
}
static
char
*
stat_uname
(
struct
stat
*
st
)
{
...
...
src/editfns.c
View file @
d32df629
...
...
@@ -45,6 +45,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#endif
#include <ctype.h>
#include <limits.h>
#include <intprops.h>
#include <strftime.h>
#include "intervals.h"
...
...
@@ -87,6 +89,7 @@ extern char **environ;
extern
Lisp_Object
w32_get_internal_run_time
(
void
);
#endif
static
void
time_overflow
(
void
)
NO_RETURN
;
static
int
tm_diff
(
struct
tm
*
,
struct
tm
*
);
static
void
find_field
(
Lisp_Object
,
Lisp_Object
,
Lisp_Object
,
EMACS_INT
*
,
Lisp_Object
,
EMACS_INT
*
);
...
...
@@ -1414,6 +1417,49 @@ DEFUN ("emacs-pid", Femacs_pid, Semacs_pid, 0, 0, 0,
return
make_number
(
getpid
());
}
#ifndef TIME_T_MIN
# define TIME_T_MIN TYPE_MINIMUM (time_t)
#endif
#ifndef TIME_T_MAX
# define TIME_T_MAX TYPE_MAXIMUM (time_t)
#endif
/* Report that a time value is out of range for Emacs. */
static
void
time_overflow
(
void
)
{
error
(
"Specified time is not representable"
);
}
/* Return the upper part of the time T (everything but the bottom 16 bits),
making sure that it is representable. */
static
EMACS_INT
hi_time
(
time_t
t
)
{
time_t
hi
=
t
>>
16
;
/* Check for overflow, helping the compiler for common cases where
no runtime check is needed, and taking care not to convert
negative numbers to unsigned before comparing them. */
if
(
!
((
!
TYPE_SIGNED
(
time_t
)
||
MOST_NEGATIVE_FIXNUM
<=
TIME_T_MIN
>>
16
||
MOST_NEGATIVE_FIXNUM
<=
hi
)
&&
(
TIME_T_MAX
>>
16
<=
MOST_POSITIVE_FIXNUM
||
hi
<=
MOST_POSITIVE_FIXNUM
)))
time_overflow
();
return
hi
;
}
/* Return the bottom 16 bits of the time T. */
static
EMACS_INT
lo_time
(
time_t
t
)
{
return
t
&
((
1
<<
16
)
-
1
);
}
DEFUN
(
"current-time"
,
Fcurrent_time
,
Scurrent_time
,
0
,
0
,
0
,
doc
:
/* Return the current time, as the number of seconds since 1970-01-01 00:00:00.
The time is returned as a list of three integers. The first has the
...
...
@@ -1428,8 +1474,8 @@ resolution finer than a second. */)
EMACS_TIME
t
;
EMACS_GET_TIME
(
t
);
return list3 (make_number ((EMACS_SECS (t)
>> 16) & 0xffff
),
make_number ((EMACS_SECS (t)
>> 0) & 0xffff
),
return
list3
(
make_number
(
hi_time
(
EMACS_SECS
(
t
)
)
),
make_number
(
lo_time
(
EMACS_SECS
(
t
)
)
),
make_number
(
EMACS_USECS
(
t
)));
}
...
...
@@ -1448,7 +1494,8 @@ on systems that do not provide resolution finer than a second. */)
{
#ifdef HAVE_GETRUSAGE
struct
rusage
usage
;
int secs, usecs;
time_t
secs
;
int
usecs
;
if
(
getrusage
(
RUSAGE_SELF
,
&
usage
)
<
0
)
/* This shouldn't happen. What action is appropriate? */
...
...
@@ -1463,8 +1510,8 @@ on systems that do not provide resolution finer than a second. */)
secs
++
;
}
return list3 (make_number (
(secs >> 16) & 0xffff
),
make_number (
(secs >> 0) & 0xffff
),
return
list3
(
make_number
(
hi_time
(
secs
)
),
make_number
(
lo_time
(
secs
)
),
make_number
(
usecs
));
#else
/* ! HAVE_GETRUSAGE */
#ifdef WINDOWSNT
...
...
@@ -1476,6 +1523,19 @@ on systems that do not provide resolution finer than a second. */)
}
/* Make a Lisp list that represents the time T. */
Lisp_Object
make_time
(
time_t
t
)
{
return
list2
(
make_number
(
hi_time
(
t
)),
make_number
(
lo_time
(
t
)));
}
/* Decode a Lisp list SPECIFIED_TIME that represents a time.
If SPECIFIED_TIME is nil, use the current time.
Set *RESULT to seconds since the Epoch.
If USEC is not null, set *USEC to the microseconds component.
Return nonzero if successful. */
int
lisp_time_argument
(
Lisp_Object
specified_time
,
time_t
*
result
,
int
*
usec
)
{
...
...
@@ -1496,6 +1556,7 @@ lisp_time_argument (Lisp_Object specified_time, time_t *result, int *usec)
else
{
Lisp_Object
high
,
low
;
EMACS_INT
hi
;
high
=
Fcar
(
specified_time
);
CHECK_NUMBER
(
high
);
low
=
Fcdr
(
specified_time
);
...
...
@@ -1519,8 +1580,21 @@ lisp_time_argument (Lisp_Object specified_time, time_t *result, int *usec)
else
if
(
usec
)
*
usec
=
0
;
CHECK_NUMBER
(
low
);
*result = (XINT (high) << 16) + (XINT (low) & 0xffff);
return *result >> 16 == XINT (high);
hi
=
XINT
(
high
);
/* Check for overflow, helping the compiler for common cases
where no runtime check is needed, and taking care not to
convert negative numbers to unsigned before comparing them. */
if
(
!
((
TYPE_SIGNED
(
time_t
)
?
(
TIME_T_MIN
>>
16
<=
MOST_NEGATIVE_FIXNUM
||
TIME_T_MIN
>>
16
<=
hi
)
:
0
<=
hi
)
&&
(
MOST_POSITIVE_FIXNUM
<=
TIME_T_MAX
>>
16
||
hi
<=
TIME_T_MAX
>>
16
)))
return
0
;
*
result
=
(
hi
<<
16
)
+
(
XINT
(
low
)
&
0xffff
);
return
1
;
}
}
...
...
@@ -1674,7 +1748,7 @@ For example, to produce full ISO 8601 format, use "%Y-%m-%dT%T%z". */)
tm
=
ut
?
gmtime
(
&
value
)
:
localtime
(
&
value
);
UNBLOCK_INPUT
;
if
(
!
tm
)
error ("Specified time is not representable"
);
time_overflow
(
);
synchronize_system_time_locale
();
...
...
@@ -1732,8 +1806,10 @@ DOW and ZONE.) */)
BLOCK_INPUT
;
decoded_time
=
localtime
(
&
time_spec
);
UNBLOCK_INPUT
;
if (! decoded_time)
error ("Specified time is not representable");
if
(
!
(
decoded_time
&&
MOST_NEGATIVE_FIXNUM
-
TM_YEAR_BASE
<=
decoded_time
->
tm_year
&&
decoded_time
->
tm_year
<=
MOST_POSITIVE_FIXNUM
-
TM_YEAR_BASE
))
time_overflow
();
XSETFASTINT
(
list_args
[
0
],
decoded_time
->
tm_sec
);
XSETFASTINT
(
list_args
[
1
],
decoded_time
->
tm_min
);
XSETFASTINT
(
list_args
[
2
],
decoded_time
->
tm_hour
);
...
...
@@ -1757,6 +1833,20 @@ DOW and ZONE.) */)
return
Flist
(
9
,
list_args
);
}
/* Return OBJ - OFFSET, checking that OBJ is a valid fixnum and that
the result is representable as an int. Assume OFFSET is small and
nonnegative. */
static
int
check_tm_member
(
Lisp_Object
obj
,
int
offset
)
{
EMACS_INT
n
;
CHECK_NUMBER
(
obj
);
n
=
XINT
(
obj
);
if
(
!
(
INT_MIN
+
offset
<=
n
&&
n
-
offset
<=
INT_MAX
))
time_overflow
();
return
n
-
offset
;
}
DEFUN
(
"encode-time"
,
Fencode_time
,
Sencode_time
,
6
,
MANY
,
0
,
doc
:
/* Convert SECOND, MINUTE, HOUR, DAY, MONTH, YEAR and ZONE to internal time.
This is the reverse operation of `decode-time', which see.
...
...
@@ -1785,19 +1875,12 @@ usage: (encode-time SECOND MINUTE HOUR DAY MONTH YEAR &optional ZONE) */)
struct
tm
tm
;
Lisp_Object
zone
=
(
nargs
>
6
?
args
[
nargs
-
1
]
:
Qnil
);
CHECK_NUMBER (args[0]); /* second */
CHECK_NUMBER (args[1]); /* minute */
CHECK_NUMBER (args[2]); /* hour */
CHECK_NUMBER (args[3]); /* day */
CHECK_NUMBER (args[4]); /* month */
CHECK_NUMBER (args[5]); /* year */
tm.tm_sec = XINT (args[0]);
tm.tm_min = XINT (args[1]);
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]) - TM_YEAR_BASE;
tm
.
tm_sec
=
check_tm_member
(
args
[
0
],
0
);
tm
.
tm_min
=
check_tm_member
(
args
[
1
],
0
);
tm
.
tm_hour
=
check_tm_member
(
args
[
2
],
0
);
tm
.
tm_mday
=
check_tm_member
(
args
[
3
],
0
);
tm
.
tm_mon
=
check_tm_member
(
args
[
4
],
1
);
tm
.
tm_year
=
check_tm_member
(
args
[
5
],
TM_YEAR_BASE
);
tm
.
tm_isdst
=
-
1
;
if
(
CONSP
(
zone
))
...
...
@@ -1846,7 +1929,7 @@ usage: (encode-time SECOND MINUTE HOUR DAY MONTH YEAR &optional ZONE) */)
}
if
(
time
==
(
time_t
)
-
1
)
error ("Specified time is not representable"
);
time_overflow
(
);
return
make_time
(
time
);
}
...
...
@@ -1881,7 +1964,7 @@ but this is considered obsolete. */)
tm
=
localtime
(
&
value
);
UNBLOCK_INPUT
;
if
(
!
(
tm
&&
TM_YEAR_IN_ASCTIME_RANGE
(
tm
->
tm_year
)
&&
(
tem
=
asctime
(
tm
))))
error ("Specified time is not representable"
);
time_overflow
(
);
/* Remove the trailing newline. */
tem
[
strlen
(
tem
)
-
1
]
=
'\0'
;
...
...
src/systime.h
View file @
d32df629
...
...
@@ -144,10 +144,8 @@ extern void set_waiting_for_input (EMACS_TIME *);
happen when this files is used outside the src directory).
Use GCPRO1 to determine if lisp.h was included. */
#ifdef GCPRO1
/* defined in dired.c */
extern
Lisp_Object
make_time
(
time_t
);
/* defined in editfns.c*/
extern
Lisp_Object
make_time
(
time_t
);
extern
int
lisp_time_argument
(
Lisp_Object
,
time_t
*
,
int
*
);
#endif
...
...
@@ -172,4 +170,3 @@ extern int lisp_time_argument (Lisp_Object, time_t *, int *);
#define EMACS_TIME_LE(T1, T2) (EMACS_TIME_CMP (T1, T2) <= 0)
#endif
/* EMACS_SYSTIME_H */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment