Merge: Cons<->int and similar integer overflow fixes.

This commit is contained in:
Paul Eggert 2011-06-06 11:36:36 -07:00
commit 0c1477cd00
26 changed files with 328 additions and 240 deletions

View file

@ -1,3 +1,8 @@
2011-06-06 Paul Eggert <eggert@cs.ucla.edu>
* Makefile.in (ALL_CFLAGS): Add -I$(srcdir)/../lib.
This is needed because lisp.h includes intprops.h now (Bug#8794).
2011-04-16 Paul Eggert <eggert@cs.ucla.edu>
Static checks with GCC 4.6.0 and non-default toolkits.

View file

@ -1,18 +1,18 @@
# Copyright (C) 1992, 1993 Lucid, Inc.
# Copyright (C) 1994, 2001-2011 Free Software Foundation, Inc.
#
#
# This file is part of the Lucid Widget Library.
#
#
# The Lucid Widget Library is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 1, or (at your option)
# any later version.
#
#
# The Lucid Widget Library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
#
# You should have received a copy of the GNU General Public License
# along with GNU Emacs; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
@ -55,7 +55,8 @@ OBJS = lwlib.o $(TOOLKIT_OBJS) lwlib-utils.o
ALL_CFLAGS= $(C_SWITCH_SYSTEM) $(C_SWITCH_X_SITE) \
$(C_SWITCH_X_SYSTEM) $(C_SWITCH_MACHINE) \
$(C_WARNINGS_SWITCH) $(PROFILING_CFLAGS) $(CFLAGS) \
-DHAVE_CONFIG_H -Demacs -I../src -I$(srcdir) -I$(srcdir)/../src
-DHAVE_CONFIG_H -Demacs -I../src \
-I$(srcdir) -I$(srcdir)/../src -I$(srcdir)/../lib
.c.o:
$(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) $<

View file

@ -1,3 +1,82 @@
2011-06-06 Paul Eggert <eggert@cs.ucla.edu>
Cons<->int and similar integer overflow fixes.
Check for overflow when converting integer to cons and back.
* charset.c (Fdefine_charset_internal, Fdecode_char):
Use cons_to_unsigned to catch overflow.
(Fencode_char): Use INTEGER_TO_CONS.
* composite.h (LGLYPH_CODE): Use cons_to_unsigned.
(LGLYPH_SET_CODE): Use INTEGER_TO_CONS.
* data.c (long_to_cons, cons_to_long): Remove.
(cons_to_unsigned, cons_to_signed): New functions.
These signal an error for invalid or out-of-range values.
* dired.c (Ffile_attributes): Use INTEGER_TO_CONS.
* fileio.c (Fset_visited_file_modtime): Use CONS_TO_INTEGER.
* font.c (Ffont_variation_glyphs):
* fontset.c (Finternal_char_font): Use INTEGER_TO_CONS.
* lisp.h: Include <intprops.h>.
(INTEGER_TO_CONS, CONS_TO_INTEGER): New macros.
(cons_to_signed, cons_to_unsigned): New decls.
(long_to_cons, cons_to_long): Remove decls.
* undo.c (record_first_change): Use INTEGER_TO_CONS.
(Fprimitive_undo): Use CONS_TO_INTEGER.
* xfns.c (Fx_window_property): Likewise.
* xselect.c: Include <limits.h>.
(x_own_selection, selection_data_to_lisp_data):
Use INTEGER_TO_CONS.
(x_handle_selection_request, x_handle_selection_clear)
(x_get_foreign_selection, Fx_disown_selection_internal)
(Fx_get_atom_name, x_send_client_event): Use CONS_TO_INTEGER.
(lisp_data_to_selection_data): Use cons_to_unsigned.
(x_fill_property_data): Use cons_to_signed.
Report values out of range.
Check for buffer and string overflow more precisely.
* buffer.h (BUF_BYTES_MAX): New macro.
* lisp.h (STRING_BYTES_MAX): New macro.
* alloc.c (Fmake_string):
* character.c (string_escape_byte8):
* coding.c (coding_alloc_by_realloc):
* doprnt.c (doprnt):
* editfns.c (Fformat):
* eval.c (verror):
Use STRING_BYTES_MAX, not MOST_POSITIVE_FIXNUM,
since they may not be the same number.
* editfns.c (Finsert_char):
* fileio.c (Finsert_file_contents):
Likewise for BUF_BYTES_MAX.
* image.c: Use ptrdiff_t, not int, for sizes.
(slurp_file): Switch from int to ptrdiff_t.
All uses changed.
(slurp_file): Check that file size fits in both size_t (for
malloc) and ptrdiff_t (for sanity and safety).
* fileio.c (Fverify_visited_file_modtime): Avoid time overflow
if b->modtime has its maximal value.
* dired.c (Ffile_attributes): Don't assume EMACS_INT has >32 bits.
Don't assume time_t can fit into int.
* buffer.h (struct buffer.modtime): Now time_t, not int.
* fileio.c (Fvisited_file_modtime): No need for time_t cast now.
* undo.c (Fprimitive_undo): Use time_t, not int, for time_t value.
Minor fixes for signed vs unsigned integers.
* character.h (MAYBE_UNIFY_CHAR):
* charset.c (maybe_unify_char):
* keyboard.c (read_char, reorder_modifiers):
XINT -> XFASTINT, since the integer must be nonnegative.
* ftfont.c (ftfont_spec_pattern):
* keymap.c (access_keymap, silly_event_symbol_error):
XUINT -> XFASTINT, since the integer must be nonnegative.
(Fsingle_key_description, preferred_sequence_p): XUINT -> XINT,
since it makes no difference and we prefer signed.
* keyboard.c (record_char): Use XUINT when all the neighbors do.
(access_keymap): NATNUMP -> INTEGERP, since the integer must be
nonnegative.
2011-06-06 Stefan Monnier <monnier@iro.umontreal.ca>
* window.h (Fwindow_frame): Declare.

View file

@ -2204,7 +2204,7 @@ INIT must be an integer that represents a character. */)
int len = CHAR_STRING (c, str);
EMACS_INT string_len = XINT (length);
if (string_len > MOST_POSITIVE_FIXNUM / len)
if (string_len > STRING_BYTES_MAX / len)
string_overflow ();
nbytes = len * string_len;
val = make_uninit_multibyte_string (string_len, nbytes);

View file

@ -306,6 +306,11 @@ do \
} \
while (0)
/* Maximum number of bytes in a buffer.
A buffer cannot contain more bytes than a 1-origin fixnum can represent,
nor can it be so large that C pointer arithmetic stops working. */
#define BUF_BYTES_MAX min (MOST_POSITIVE_FIXNUM - 1, min (SIZE_MAX, PTRDIFF_MAX))
/* Return the address of byte position N in current buffer. */
#define BYTE_POS_ADDR(n) \
@ -545,7 +550,7 @@ struct buffer
-1 means visited file was nonexistent.
0 means visited file modtime unknown; in no case complain
about any mismatch on next save attempt. */
int modtime;
time_t modtime;
/* Size of the file when modtime was set. This is used to detect the
case where the file grew while we were reading it, so the modtime
is still the same (since it's rounded up to seconds) but we're actually

View file

@ -838,7 +838,7 @@ string_escape_byte8 (Lisp_Object string)
if (multibyte)
{
if ((MOST_POSITIVE_FIXNUM - nchars) / 3 < byte8_count
|| (MOST_POSITIVE_FIXNUM - nbytes) / 2 < byte8_count)
|| (STRING_BYTES_MAX - nbytes) / 2 < byte8_count)
string_overflow ();
/* Convert 2-byte sequence of byte8 chars to 4-byte octal. */
@ -847,7 +847,7 @@ string_escape_byte8 (Lisp_Object string)
}
else
{
if ((MOST_POSITIVE_FIXNUM - nchars) / 3 < byte8_count)
if ((STRING_BYTES_MAX - nchars) / 3 < byte8_count)
string_overflow ();
/* Convert 1-byte sequence of byte8 chars to 4-byte octal. */

View file

@ -544,7 +544,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
Lisp_Object val; \
val = CHAR_TABLE_REF (Vchar_unify_table, c); \
if (INTEGERP (val)) \
c = XINT (val); \
c = XFASTINT (val); \
else if (! NILP (val)) \
c = maybe_unify_char (c, val); \
} \

View file

@ -932,17 +932,8 @@ usage: (define-charset-internal ...) */)
val = args[charset_arg_min_code];
if (! NILP (val))
{
unsigned code;
unsigned code = cons_to_unsigned (val, UINT_MAX);
if (INTEGERP (val))
code = XINT (val);
else
{
CHECK_CONS (val);
CHECK_NUMBER_CAR (val);
CHECK_NUMBER_CDR (val);
code = (XINT (XCAR (val)) << 16) | (XINT (XCDR (val)));
}
if (code < charset.min_code
|| code > charset.max_code)
args_out_of_range_3 (make_number (charset.min_code),
@ -954,17 +945,8 @@ usage: (define-charset-internal ...) */)
val = args[charset_arg_max_code];
if (! NILP (val))
{
unsigned code;
unsigned code = cons_to_unsigned (val, UINT_MAX);
if (INTEGERP (val))
code = XINT (val);
else
{
CHECK_CONS (val);
CHECK_NUMBER_CAR (val);
CHECK_NUMBER_CDR (val);
code = (XINT (XCAR (val)) << 16) | (XINT (XCDR (val)));
}
if (code < charset.min_code
|| code > charset.max_code)
args_out_of_range_3 (make_number (charset.min_code),
@ -1637,7 +1619,7 @@ maybe_unify_char (int c, Lisp_Object val)
struct charset *charset;
if (INTEGERP (val))
return XINT (val);
return XFASTINT (val);
if (NILP (val))
return c;
@ -1647,7 +1629,7 @@ maybe_unify_char (int c, Lisp_Object val)
{
val = CHAR_TABLE_REF (Vchar_unify_table, c);
if (! NILP (val))
c = XINT (val);
c = XFASTINT (val);
}
else
{
@ -1865,17 +1847,7 @@ and CODE-POINT to a character. Currently not supported and just ignored. */)
struct charset *charsetp;
CHECK_CHARSET_GET_ID (charset, id);
if (CONSP (code_point))
{
CHECK_NATNUM_CAR (code_point);
CHECK_NATNUM_CDR (code_point);
code = (XINT (XCAR (code_point)) << 16) | (XINT (XCDR (code_point)));
}
else
{
CHECK_NATNUM (code_point);
code = XINT (code_point);
}
code = cons_to_unsigned (code_point, UINT_MAX);
charsetp = CHARSET_FROM_ID (id);
c = DECODE_CHAR (charsetp, code);
return (c >= 0 ? make_number (c) : Qnil);
@ -1900,9 +1872,7 @@ code-point in CCS. Currently not supported and just ignored. */)
code = ENCODE_CHAR (charsetp, XINT (ch));
if (code == CHARSET_INVALID_CODE (charsetp))
return Qnil;
if (code > 0x7FFFFFF)
return Fcons (make_number (code >> 16), make_number (code & 0xFFFF));
return make_number (code);
return INTEGER_TO_CONS (code);
}

View file

@ -1071,8 +1071,8 @@ coding_set_destination (struct coding_system *coding)
static void
coding_alloc_by_realloc (struct coding_system *coding, EMACS_INT bytes)
{
if (coding->dst_bytes >= MOST_POSITIVE_FIXNUM - bytes)
error ("Maximum size of buffer or string exceeded");
if (STRING_BYTES_MAX - coding->dst_bytes < bytes)
string_overflow ();
coding->destination = (unsigned char *) xrealloc (coding->destination,
coding->dst_bytes + bytes);
coding->dst_bytes += bytes;

View file

@ -265,10 +265,7 @@ enum lglyph_indices
#define LGLYPH_CODE(g) \
(NILP (AREF ((g), LGLYPH_IX_CODE)) \
? FONT_INVALID_CODE \
: CONSP (AREF ((g), LGLYPH_IX_CODE)) \
? ((XFASTINT (XCAR (AREF ((g), LGLYPH_IX_CODE))) << 16) \
| (XFASTINT (XCDR (AREF ((g), LGLYPH_IX_CODE))))) \
: XFASTINT (AREF ((g), LGLYPH_IX_CODE)))
: cons_to_unsigned (AREF (g, LGLYPH_IX_CODE), TYPE_MAXIMUM (unsigned)))
#define LGLYPH_WIDTH(g) XINT (AREF ((g), LGLYPH_IX_WIDTH))
#define LGLYPH_LBEARING(g) XINT (AREF ((g), LGLYPH_IX_LBEARING))
#define LGLYPH_RBEARING(g) XINT (AREF ((g), LGLYPH_IX_RBEARING))
@ -280,15 +277,8 @@ enum lglyph_indices
#define LGLYPH_SET_CHAR(g, val) ASET ((g), LGLYPH_IX_CHAR, make_number (val))
/* Callers must assure that VAL is not negative! */
#define LGLYPH_SET_CODE(g, val) \
do { \
if (val == FONT_INVALID_CODE) \
ASET ((g), LGLYPH_IX_CODE, Qnil); \
else if ((EMACS_INT)val > MOST_POSITIVE_FIXNUM) \
ASET ((g), LGLYPH_IX_CODE, Fcons (make_number ((val) >> 16), \
make_number ((val) & 0xFFFF))); \
else \
ASET ((g), LGLYPH_IX_CODE, make_number (val)); \
} while (0)
ASET (g, LGLYPH_IX_CODE, \
val == FONT_INVALID_CODE ? Qnil : INTEGER_TO_CONS (val))
#define LGLYPH_SET_WIDTH(g, val) ASET ((g), LGLYPH_IX_WIDTH, make_number (val))
#define LGLYPH_SET_LBEARING(g, val) ASET ((g), LGLYPH_IX_LBEARING, make_number (val))

View file

@ -2326,33 +2326,110 @@ DEFUN ("zerop", Fzerop, Szerop, 1, 1, 0,
return Qnil;
}
/* Convert between long values and pairs of Lisp integers.
Note that long_to_cons returns a single Lisp integer
when the value fits in one. */
Lisp_Object
long_to_cons (long unsigned int i)
/* Convert the cons-of-integers, integer, or float value C to an
unsigned value with maximum value MAX. Signal an error if C does not
have a valid format or is out of range. */
uintmax_t
cons_to_unsigned (Lisp_Object c, uintmax_t max)
{
unsigned long top = i >> 16;
unsigned int bot = i & 0xFFFF;
if (top == 0)
return make_number (bot);
if (top == (unsigned long)-1 >> 16)
return Fcons (make_number (-1), make_number (bot));
return Fcons (make_number (top), make_number (bot));
int valid = 0;
uintmax_t val IF_LINT (= 0);
if (INTEGERP (c))
{
valid = 0 <= XINT (c);
val = XINT (c);
}
else if (FLOATP (c))
{
double d = XFLOAT_DATA (c);
if (0 <= d
&& d < (max == UINTMAX_MAX ? (double) UINTMAX_MAX + 1 : max + 1))
{
val = d;
valid = 1;
}
}
else if (CONSP (c) && NATNUMP (XCAR (c)))
{
uintmax_t top = XFASTINT (XCAR (c));
Lisp_Object rest = XCDR (c);
if (top <= UINTMAX_MAX >> 24 >> 16
&& CONSP (rest)
&& NATNUMP (XCAR (rest)) && XFASTINT (XCAR (rest)) < 1 << 24
&& NATNUMP (XCDR (rest)) && XFASTINT (XCDR (rest)) < 1 << 16)
{
uintmax_t mid = XFASTINT (XCAR (rest));
val = top << 24 << 16 | mid << 16 | XFASTINT (XCDR (rest));
valid = 1;
}
else if (top <= UINTMAX_MAX >> 16)
{
if (CONSP (rest))
rest = XCAR (rest);
if (NATNUMP (rest) && XFASTINT (rest) < 1 << 16)
{
val = top << 16 | XFASTINT (rest);
valid = 1;
}
}
}
if (! (valid && val <= max))
error ("Not an in-range integer, float, or cons of integers");
return val;
}
unsigned long
cons_to_long (Lisp_Object c)
/* Convert the cons-of-integers, integer, or float value C to a signed
value with extrema MIN and MAX. Signal an error if C does not have
a valid format or is out of range. */
intmax_t
cons_to_signed (Lisp_Object c, intmax_t min, intmax_t max)
{
Lisp_Object top, bot;
int valid = 0;
intmax_t val IF_LINT (= 0);
if (INTEGERP (c))
return XINT (c);
top = XCAR (c);
bot = XCDR (c);
if (CONSP (bot))
bot = XCAR (bot);
return ((XINT (top) << 16) | XINT (bot));
{
val = XINT (c);
valid = 1;
}
else if (FLOATP (c))
{
double d = XFLOAT_DATA (c);
if (min <= d
&& d < (max == INTMAX_MAX ? (double) INTMAX_MAX + 1 : max + 1))
{
val = d;
valid = 1;
}
}
else if (CONSP (c) && INTEGERP (XCAR (c)))
{
intmax_t top = XINT (XCAR (c));
Lisp_Object rest = XCDR (c);
if (INTMAX_MIN >> 24 >> 16 <= top && top <= INTMAX_MAX >> 24 >> 16
&& CONSP (rest)
&& NATNUMP (XCAR (rest)) && XFASTINT (XCAR (rest)) < 1 << 24
&& NATNUMP (XCDR (rest)) && XFASTINT (XCDR (rest)) < 1 << 16)
{
intmax_t mid = XFASTINT (XCAR (rest));
val = top << 24 << 16 | mid << 16 | XFASTINT (XCDR (rest));
valid = 1;
}
else if (INTMAX_MIN >> 16 <= top && top <= INTMAX_MAX >> 16)
{
if (CONSP (rest))
rest = XCAR (rest);
if (NATNUMP (rest) && XFASTINT (rest) < 1 << 16)
{
val = top << 16 | XFASTINT (rest);
valid = 1;
}
}
}
if (! (valid && min <= val && val <= max))
error ("Not an in-range integer, float, or cons of integers");
return val;
}
DEFUN ("number-to-string", Fnumber_to_string, Snumber_to_string, 1, 1, 0,

View file

@ -900,11 +900,10 @@ Elements of the attribute list are:
This is a floating point number if the size is too large for an integer.
8. File modes, as a string of ten letters or dashes as in ls -l.
9. t if file's gid would change if file were deleted and recreated.
10. inode number. If inode number is larger than what Emacs integer
can hold, but still fits into a 32-bit number, this is a cons cell
containing two integers: first the high part, then the low 16 bits.
If the inode number is wider than 32 bits, this is of the form
(HIGH MIDDLE . LOW): first the high 24 bits, then middle 24 bits,
10. inode number. If it is larger than what an Emacs integer can hold,
this is of the form (HIGH . LOW): first the high bits, then the low 16 bits.
If even HIGH is too large for an Emacs integer, this is instead of the form
(HIGH MIDDLE . LOW): first the high bits, then the middle 24 bits,
and finally the low 16 bits.
11. Filesystem device number. If it is larger than what the Emacs
integer can hold, this is a cons cell, similar to the inode number.
@ -998,35 +997,8 @@ so last access time will always be midnight of that day. */)
#else /* file gid will be egid */
values[9] = (s.st_gid != getegid ()) ? Qt : Qnil;
#endif /* not BSD4_2 */
if (!FIXNUM_OVERFLOW_P (s.st_ino))
/* Keep the most common cases as integers. */
values[10] = make_number (s.st_ino);
else if (!FIXNUM_OVERFLOW_P (s.st_ino >> 16))
/* To allow inode numbers larger than VALBITS, separate the bottom
16 bits. */
values[10] = Fcons (make_number ((EMACS_INT)(s.st_ino >> 16)),
make_number ((EMACS_INT)(s.st_ino & 0xffff)));
else
{
/* To allow inode numbers beyond 32 bits, separate into 2 24-bit
high parts and a 16-bit bottom part.
The code on the next line avoids a compiler warning on
systems where st_ino is 32 bit wide. (bug#766). */
EMACS_INT high_ino = s.st_ino >> 31 >> 1;
EMACS_INT low_ino = s.st_ino & 0xffffffff;
values[10] = Fcons (make_number (high_ino >> 8),
Fcons (make_number (((high_ino & 0xff) << 16)
+ (low_ino >> 16)),
make_number (low_ino & 0xffff)));
}
/* Likewise for device. */
if (FIXNUM_OVERFLOW_P (s.st_dev))
values[11] = Fcons (make_number (s.st_dev >> 16),
make_number (s.st_dev & 0xffff));
else
values[11] = make_number (s.st_dev);
values[10] = INTEGER_TO_CONS (s.st_ino);
values[11] = INTEGER_TO_CONS (s.st_dev);
return Flist (sizeof(values) / sizeof(values[0]), values);
}

View file

@ -329,7 +329,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format,
minlen = atoi (&fmtcpy[1]);
string = va_arg (ap, char *);
tem = strlen (string);
if (tem > MOST_POSITIVE_FIXNUM)
if (tem > STRING_BYTES_MAX)
error ("String for %%s or %%S format is too long");
width = strwidth (string, tem);
goto doit1;
@ -338,7 +338,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format,
doit:
/* Coming here means STRING contains ASCII only. */
tem = strlen (string);
if (tem > MOST_POSITIVE_FIXNUM)
if (tem > STRING_BYTES_MAX)
error ("Format width or precision too large");
width = tem;
doit1:

View file

@ -2342,7 +2342,7 @@ from adjoining text, if those properties are sticky. */)
len = CHAR_STRING (XFASTINT (character), str);
else
str[0] = XFASTINT (character), len = 1;
if (MOST_POSITIVE_FIXNUM / len < XINT (count))
if (BUF_BYTES_MAX / len < XINT (count))
error ("Maximum buffer size would be exceeded");
n = XINT (count) * len;
if (n <= 0)
@ -3589,7 +3589,7 @@ usage: (format STRING &rest OBJECTS) */)
char initial_buffer[4000];
char *buf = initial_buffer;
EMACS_INT bufsize = sizeof initial_buffer;
EMACS_INT max_bufsize = min (MOST_POSITIVE_FIXNUM + 1, SIZE_MAX);
EMACS_INT max_bufsize = STRING_BYTES_MAX + 1;
char *p;
Lisp_Object buf_save_value IF_LINT (= {0});
register char *format, *end, *format_start;

View file

@ -1994,7 +1994,7 @@ verror (const char *m, va_list ap)
{
char buf[4000];
size_t size = sizeof buf;
size_t size_max = min (MOST_POSITIVE_FIXNUM + 1, SIZE_MAX);
size_t size_max = STRING_BYTES_MAX + 1;
size_t mlen = strlen (m);
char *buffer = buf;
size_t used;

View file

@ -3248,7 +3248,7 @@ variable `last-coding-system-used' to the coding system actually used. */)
/* Check whether the size is too large or negative, which can happen on a
platform that allows file sizes greater than the maximum off_t value. */
if (! not_regular
&& ! (0 <= st.st_size && st.st_size <= MOST_POSITIVE_FIXNUM))
&& ! (0 <= st.st_size && st.st_size <= BUF_BYTES_MAX))
error ("Maximum buffer size exceeded");
/* Prevent redisplay optimizations. */
@ -4960,7 +4960,7 @@ See Info node `(elisp)Modification Time' for more details. */)
if ((st.st_mtime == b->modtime
/* If both are positive, accept them if they are off by one second. */
|| (st.st_mtime > 0 && b->modtime > 0
&& (st.st_mtime == b->modtime + 1
&& (st.st_mtime - 1 == b->modtime
|| st.st_mtime == b->modtime - 1)))
&& (st.st_size == b->modtime_size
|| b->modtime_size < 0))
@ -4990,7 +4990,7 @@ See Info node `(elisp)Modification Time' for more details. */)
{
if (! current_buffer->modtime)
return make_number (0);
return make_time ((time_t) current_buffer->modtime);
return make_time (current_buffer->modtime);
}
DEFUN ("set-visited-file-modtime", Fset_visited_file_modtime,
@ -5005,7 +5005,7 @@ An argument specifies the modification time value to use
{
if (!NILP (time_list))
{
current_buffer->modtime = cons_to_long (time_list);
CONS_TO_INTEGER (time_list, time_t, current_buffer->modtime);
current_buffer->modtime_size = -1;
}
else

View file

@ -4388,16 +4388,8 @@ where
for (i = 0; i < 255; i++)
if (variations[i])
{
Lisp_Object code;
int vs = (i < 16 ? 0xFE00 + i : 0xE0100 + (i - 16));
/* Stops GCC whining about limited range of data type. */
EMACS_INT var = variations[i];
if (var > MOST_POSITIVE_FIXNUM)
code = Fcons (make_number ((variations[i]) >> 16),
make_number ((variations[i]) & 0xFFFF));
else
code = make_number (variations[i]);
Lisp_Object code = INTEGER_TO_CONS (variations[i]);
val = Fcons (Fcons (make_number (vs), code), val);
}
return val;

View file

@ -1859,17 +1859,11 @@ DEFUN ("internal-char-font", Finternal_char_font, Sinternal_char_font, 1, 2, 0,
{
unsigned code = face->font->driver->encode_char (face->font, c);
Lisp_Object font_object;
/* Assignment to EMACS_INT stops GCC whining about limited range
of data type. */
EMACS_INT cod = code;
if (code == FONT_INVALID_CODE)
return Qnil;
XSETFONT (font_object, face->font);
if (cod <= MOST_POSITIVE_FIXNUM)
return Fcons (font_object, make_number (code));
return Fcons (font_object, Fcons (make_number (code >> 16),
make_number (code & 0xFFFF)));
return Fcons (font_object, INTEGER_TO_CONS (code));
}
return Qnil;
}

View file

@ -815,7 +815,7 @@ ftfont_spec_pattern (Lisp_Object spec, char *otlayout, struct OpenTypeSpec **ots
goto err;
for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
if (CHARACTERP (XCAR (chars))
&& ! FcCharSetAddChar (charset, XUINT (XCAR (chars))))
&& ! FcCharSetAddChar (charset, XFASTINT (XCAR (chars))))
goto err;
}
}

View file

@ -2112,9 +2112,6 @@ x_put_x_image (struct frame *f, XImagePtr ximg, Pixmap pixmap, int width, int he
File Handling
***********************************************************************/
static unsigned char *slurp_file (char *, int *);
/* Find image file FILE. Look in data-directory/images, then
x-bitmap-file-path. Value is the encoded full name of the file
found, or nil if not found. */
@ -2151,7 +2148,7 @@ x_find_image_file (Lisp_Object file)
occurred. *SIZE is set to the size of the file. */
static unsigned char *
slurp_file (char *file, int *size)
slurp_file (char *file, ptrdiff_t *size)
{
FILE *fp = NULL;
unsigned char *buf = NULL;
@ -2159,6 +2156,7 @@ slurp_file (char *file, int *size)
if (stat (file, &st) == 0
&& (fp = fopen (file, "rb")) != NULL
&& 0 <= st.st_size && st.st_size <= min (PTRDIFF_MAX, SIZE_MAX)
&& (buf = (unsigned char *) xmalloc (st.st_size),
fread (buf, 1, st.st_size, fp) == st.st_size))
{
@ -2814,7 +2812,7 @@ xbm_load (struct frame *f, struct image *img)
{
Lisp_Object file;
unsigned char *contents;
int size;
ptrdiff_t size;
file = x_find_image_file (file_name);
if (!STRINGP (file))
@ -4039,7 +4037,7 @@ xpm_load (struct frame *f,
{
Lisp_Object file;
unsigned char *contents;
int size;
ptrdiff_t size;
file = x_find_image_file (file_name);
if (!STRINGP (file))
@ -5021,6 +5019,7 @@ pbm_read_file (file, size)
if (stat (SDATA (file), &st) == 0
&& (fp = fopen (SDATA (file), "rb")) != NULL
&& 0 <= st.st_size && st.st_size <= min (PTRDIFF_MAX, SIZE_MAX)
&& (buf = (char *) xmalloc (st.st_size),
fread (buf, 1, st.st_size, fp) == st.st_size))
{
@ -5055,7 +5054,7 @@ pbm_load (struct frame *f, struct image *img)
enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
unsigned char *contents = NULL;
unsigned char *end, *p;
int size;
ptrdiff_t size;
specified_file = image_spec_value (img->spec, QCfile, NULL);
@ -7869,7 +7868,7 @@ static int svg_image_p (Lisp_Object object);
static int svg_load (struct frame *f, struct image *img);
static int svg_load_image (struct frame *, struct image *,
unsigned char *, unsigned int);
unsigned char *, ptrdiff_t);
/* The symbol `svg' identifying images of this type. */
@ -8047,7 +8046,7 @@ svg_load (struct frame *f, struct image *img)
{
Lisp_Object file;
unsigned char *contents;
int size;
ptrdiff_t size;
file = x_find_image_file (file_name);
if (!STRINGP (file))
@ -8096,7 +8095,7 @@ static int
svg_load_image (struct frame *f, /* Pointer to emacs frame structure. */
struct image *img, /* Pointer to emacs image structure. */
unsigned char *contents, /* String containing the SVG XML data to be parsed. */
unsigned int size) /* Size of data in bytes. */
ptrdiff_t size) /* Size of data in bytes. */
{
RsvgHandle *rsvg_handle;
RsvgDimensionData dimension_data;

View file

@ -2395,8 +2395,8 @@ read_char (int commandflag, int nmaps, Lisp_Object *maps, Lisp_Object prev_event
c = Faref (Vexecuting_kbd_macro, make_number (executing_kbd_macro_index));
if (STRINGP (Vexecuting_kbd_macro)
&& (XINT (c) & 0x80) && (XUINT (c) <= 0xff))
XSETFASTINT (c, CHAR_META | (XINT (c) & ~0x80));
&& (XFASTINT (c) & 0x80) && (XFASTINT (c) <= 0xff))
XSETFASTINT (c, CHAR_META | (XFASTINT (c) & ~0x80));
executing_kbd_macro_index++;
@ -3321,7 +3321,7 @@ record_char (Lisp_Object c)
if (INTEGERP (c))
{
if (XUINT (c) < 0x100)
putc (XINT (c), dribble);
putc (XUINT (c), dribble);
else
fprintf (dribble, " 0x%"pI"x", XUINT (c));
}
@ -6370,7 +6370,7 @@ reorder_modifiers (Lisp_Object symbol)
Lisp_Object parsed;
parsed = parse_modifiers (symbol);
return apply_modifiers ((int) XINT (XCAR (XCDR (parsed))),
return apply_modifiers (XFASTINT (XCAR (XCDR (parsed))),
XCAR (parsed));
}

View file

@ -462,7 +462,7 @@ access_keymap (Lisp_Object map, Lisp_Object idx, int t_ok, int noinherit, int au
XSETFASTINT (idx, XINT (idx) & (CHAR_META | (CHAR_META - 1)));
/* Handle the special meta -> esc mapping. */
if (INTEGERP (idx) && XUINT (idx) & meta_modifier)
if (INTEGERP (idx) && XFASTINT (idx) & meta_modifier)
{
/* See if there is a meta-map. If there's none, there is
no binding for IDX, unless a default binding exists in MAP. */
@ -480,7 +480,7 @@ access_keymap (Lisp_Object map, Lisp_Object idx, int t_ok, int noinherit, int au
if (CONSP (event_meta_map))
{
map = event_meta_map;
idx = make_number (XUINT (idx) & ~meta_modifier);
idx = make_number (XFASTINT (idx) & ~meta_modifier);
}
else if (t_ok)
/* Set IDX to t, so that we only find a default binding. */
@ -529,7 +529,7 @@ access_keymap (Lisp_Object map, Lisp_Object idx, int t_ok, int noinherit, int au
}
else if (VECTORP (binding))
{
if (NATNUMP (idx) && XFASTINT (idx) < ASIZE (binding))
if (INTEGERP (idx) && XFASTINT (idx) < ASIZE (binding))
val = AREF (binding, XFASTINT (idx));
}
else if (CHAR_TABLE_P (binding))
@ -537,7 +537,7 @@ access_keymap (Lisp_Object map, Lisp_Object idx, int t_ok, int noinherit, int au
/* Character codes with modifiers
are not included in a char-table.
All character codes without modifiers are included. */
if (NATNUMP (idx) && (XFASTINT (idx) & CHAR_MODIFIER_MASK) == 0)
if (INTEGERP (idx) && (XFASTINT (idx) & CHAR_MODIFIER_MASK) == 0)
{
val = Faref (binding, idx);
/* `nil' has a special meaning for char-tables, so
@ -1357,7 +1357,7 @@ silly_event_symbol_error (Lisp_Object c)
int modifiers;
parsed = parse_modifiers (c);
modifiers = (int) XUINT (XCAR (XCDR (parsed)));
modifiers = XFASTINT (XCAR (XCDR (parsed)));
base = XCAR (parsed);
name = Fsymbol_name (base);
/* This alist includes elements such as ("RET" . "\\r"). */
@ -2416,7 +2416,7 @@ around function keys and event symbols. */)
{
char tem[KEY_DESCRIPTION_SIZE];
*push_key_description (XUINT (key), tem, 1) = 0;
*push_key_description (XINT (key), tem, 1) = 0;
return build_string (tem);
}
else if (SYMBOLP (key)) /* Function key or event-symbol */
@ -2515,7 +2515,7 @@ preferred_sequence_p (Lisp_Object seq)
return 0;
else
{
int modifiers = XUINT (elt) & (CHAR_MODIFIER_MASK & ~CHAR_META);
int modifiers = XINT (elt) & (CHAR_MODIFIER_MASK & ~CHAR_META);
if (modifiers == where_is_preferred_modifier)
result = 2;
else if (modifiers)

View file

@ -24,6 +24,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <stddef.h>
#include <inttypes.h>
#include <intprops.h>
/* Use the configure flag --enable-checking[=LIST] to enable various
types of run time checks for Lisp objects. */
@ -763,6 +765,12 @@ extern EMACS_INT string_bytes (struct Lisp_String *);
#endif /* not GC_CHECK_STRING_BYTES */
/* A string cannot contain more bytes than a fixnum can represent,
nor can it be so long that C pointer arithmetic stops working on
the string plus a terminating null. */
#define STRING_BYTES_MAX \
min (MOST_POSITIVE_FIXNUM, min (SIZE_MAX, PTRDIFF_MAX) - 1)
/* Mark STR as a unibyte string. */
#define STRING_SET_UNIBYTE(STR) \
do { if (EQ (STR, empty_multibyte_string)) \
@ -2402,9 +2410,35 @@ EXFUN (Fadd1, 1);
EXFUN (Fsub1, 1);
EXFUN (Fmake_variable_buffer_local, 1);
/* Convert the integer I to an Emacs representation, either the integer
itself, or a cons of two or three integers, or if all else fails a float.
I should not have side effects. */
#define INTEGER_TO_CONS(i) \
(! FIXNUM_OVERFLOW_P (i) \
? make_number (i) \
: ! ((FIXNUM_OVERFLOW_P (INTMAX_MIN >> 16) \
|| FIXNUM_OVERFLOW_P (UINTMAX_MAX >> 16)) \
&& FIXNUM_OVERFLOW_P ((i) >> 16)) \
? Fcons (make_number ((i) >> 16), make_number ((i) & 0xffff)) \
: ! ((FIXNUM_OVERFLOW_P (INTMAX_MIN >> 16 >> 24) \
|| FIXNUM_OVERFLOW_P (UINTMAX_MAX >> 16 >> 24)) \
&& FIXNUM_OVERFLOW_P ((i) >> 16 >> 24)) \
? Fcons (make_number ((i) >> 16 >> 24), \
Fcons (make_number ((i) >> 16 & 0xffffff), \
make_number ((i) & 0xffff))) \
: make_float (i))
/* Convert the Emacs representation CONS back to an integer of type
TYPE, storing the result the variable VAR. Signal an error if CONS
is not a valid representation or is out of range for TYPE. */
#define CONS_TO_INTEGER(cons, type, var) \
(TYPE_SIGNED (type) \
? ((var) = cons_to_signed (cons, TYPE_MINIMUM (type), TYPE_MAXIMUM (type))) \
: ((var) = cons_to_unsigned (cons, TYPE_MAXIMUM (type))))
extern intmax_t cons_to_signed (Lisp_Object, intmax_t, intmax_t);
extern uintmax_t cons_to_unsigned (Lisp_Object, uintmax_t);
extern struct Lisp_Symbol *indirect_variable (struct Lisp_Symbol *);
extern Lisp_Object long_to_cons (unsigned long);
extern unsigned long cons_to_long (Lisp_Object);
extern void args_out_of_range (Lisp_Object, Lisp_Object) NO_RETURN;
extern void args_out_of_range_3 (Lisp_Object, Lisp_Object,
Lisp_Object) NO_RETURN;

View file

@ -212,7 +212,6 @@ record_change (EMACS_INT beg, EMACS_INT length)
void
record_first_change (void)
{
Lisp_Object high, low;
struct buffer *base_buffer = current_buffer;
if (EQ (BVAR (current_buffer, undo_list), Qt))
@ -225,9 +224,9 @@ record_first_change (void)
if (base_buffer->base_buffer)
base_buffer = base_buffer->base_buffer;
XSETFASTINT (high, (base_buffer->modtime >> 16) & 0xffff);
XSETFASTINT (low, base_buffer->modtime & 0xffff);
BVAR (current_buffer, undo_list) = Fcons (Fcons (Qt, Fcons (high, low)), BVAR (current_buffer, undo_list));
BVAR (current_buffer, undo_list) =
Fcons (Fcons (Qt, INTEGER_TO_CONS (base_buffer->modtime)),
BVAR (current_buffer, undo_list));
}
/* Record a change in property PROP (whose old value was VAL)
@ -499,13 +498,9 @@ Return what remains of the list. */)
if (EQ (car, Qt))
{
/* Element (t high . low) records previous modtime. */
Lisp_Object high, low;
int mod_time;
struct buffer *base_buffer = current_buffer;
high = Fcar (cdr);
low = Fcdr (cdr);
mod_time = (XFASTINT (high) << 16) + XFASTINT (low);
time_t mod_time;
CONS_TO_INTEGER (cdr, time_t, mod_time);
if (current_buffer->base_buffer)
base_buffer = current_buffer->base_buffer;

View file

@ -4299,18 +4299,9 @@ no value of TYPE (always string in the MS Windows case). */)
if (! NILP (source))
{
if (NUMBERP (source))
{
if (FLOATP (source))
target_window = (Window) XFLOAT (source);
else
target_window = XFASTINT (source);
if (target_window == 0)
target_window = FRAME_X_DISPLAY_INFO (f)->root_window;
}
else if (CONSP (source))
target_window = cons_to_long (source);
CONS_TO_INTEGER (source, Window, target_window);
if (! target_window)
target_window = FRAME_X_DISPLAY_INFO (f)->root_window;
}
BLOCK_INPUT;

View file

@ -20,6 +20,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
/* Rewritten by jwz */
#include <config.h>
#include <limits.h>
#include <stdio.h> /* termhooks.h needs this */
#include <setjmp.h>
@ -335,7 +336,7 @@ x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value,
Lisp_Object prev_value;
selection_data = list4 (selection_name, selection_value,
long_to_cons (timestamp), frame);
INTEGER_TO_CONS (timestamp), frame);
prev_value = LOCAL_SELECTION (selection_name, dpyinfo);
dpyinfo->terminal->Vselection_alist
@ -419,7 +420,7 @@ x_get_local_selection (Lisp_Object selection_symbol, Lisp_Object target_type,
|| INTEGERP (check)
|| NILP (value))
return value;
/* Check for a value that cons_to_long could handle. */
/* Check for a value that CONS_TO_INTEGER could handle. */
else if (CONSP (check)
&& INTEGERP (XCAR (check))
&& (INTEGERP (XCDR (check))
@ -782,8 +783,8 @@ x_handle_selection_request (struct input_event *event)
if (NILP (local_selection_data)) goto DONE;
/* Decline requests issued prior to our acquiring the selection. */
local_selection_time
= (Time) cons_to_long (XCAR (XCDR (XCDR (local_selection_data))));
CONS_TO_INTEGER (XCAR (XCDR (XCDR (local_selection_data))),
Time, local_selection_time);
if (SELECTION_EVENT_TIME (event) != CurrentTime
&& local_selection_time > SELECTION_EVENT_TIME (event))
goto DONE;
@ -950,8 +951,8 @@ x_handle_selection_clear (struct input_event *event)
/* Well, we already believe that we don't own it, so that's just fine. */
if (NILP (local_selection_data)) return;
local_selection_time = (Time)
cons_to_long (XCAR (XCDR (XCDR (local_selection_data))));
CONS_TO_INTEGER (XCAR (XCDR (XCDR (local_selection_data))),
Time, local_selection_time);
/* We have reasserted the selection since this SelectionClear was
generated, so we can disregard it. */
@ -1212,16 +1213,7 @@ x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type,
return Qnil;
if (! NILP (time_stamp))
{
if (CONSP (time_stamp))
requestor_time = (Time) cons_to_long (time_stamp);
else if (INTEGERP (time_stamp))
requestor_time = (Time) XUINT (time_stamp);
else if (FLOATP (time_stamp))
requestor_time = (Time) XFLOAT_DATA (time_stamp);
else
error ("TIME_STAMP must be cons or number");
}
CONS_TO_INTEGER (time_stamp, Time, requestor_time);
BLOCK_INPUT;
TRACE2 ("Get selection %s, type %s",
@ -1639,7 +1631,7 @@ selection_data_to_lisp_data (Display *display, const unsigned char *data,
convert it to a cons of integers, 16 bits in each half.
*/
else if (format == 32 && size == sizeof (int))
return long_to_cons (((unsigned int *) data) [0]);
return INTEGER_TO_CONS (((unsigned int *) data) [0]);
else if (format == 16 && size == sizeof (short))
return make_number ((int) (((unsigned short *) data) [0]));
@ -1665,7 +1657,7 @@ selection_data_to_lisp_data (Display *display, const unsigned char *data,
for (i = 0; i < size / 4; i++)
{
unsigned int j = ((unsigned int *) data) [i];
Faset (v, make_number (i), long_to_cons (j));
Faset (v, make_number (i), INTEGER_TO_CONS (j));
}
return v;
}
@ -1742,7 +1734,7 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj,
*size_ret = 1;
*data_ret = (unsigned char *) xmalloc (sizeof (long) + 1);
(*data_ret) [sizeof (long)] = 0;
(*(unsigned long **) data_ret) [0] = cons_to_long (obj);
(*(unsigned long **) data_ret) [0] = cons_to_unsigned (obj, ULONG_MAX);
if (NILP (type)) type = QINTEGER;
}
else if (VECTORP (obj))
@ -1790,11 +1782,11 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj,
*data_ret = (unsigned char *) xmalloc (*size_ret * data_size);
for (i = 0; i < *size_ret; i++)
if (*format_ret == 32)
(*((unsigned long **) data_ret)) [i]
= cons_to_long (XVECTOR (obj)->contents [i]);
(*((unsigned long **) data_ret)) [i] =
cons_to_unsigned (XVECTOR (obj)->contents [i], ULONG_MAX);
else
(*((unsigned short **) data_ret)) [i]
= (unsigned short) cons_to_long (XVECTOR (obj)->contents [i]);
(*((unsigned short **) data_ret)) [i] =
cons_to_unsigned (XVECTOR (obj)->contents [i], USHRT_MAX);
}
}
else
@ -2012,8 +2004,10 @@ frame's display, or the first available X display. */)
selection_atom = symbol_to_x_atom (dpyinfo, selection);
BLOCK_INPUT;
timestamp = (NILP (time_object) ? last_event_timestamp
: cons_to_long (time_object));
if (NILP (time_object))
timestamp = last_event_timestamp;
else
CONS_TO_INTEGER (time_object, Time, timestamp);
XSetSelectionOwner (dpyinfo->display, selection_atom, None, timestamp);
UNBLOCK_INPUT;
@ -2250,12 +2244,8 @@ x_fill_property_data (Display *dpy, Lisp_Object data, void *ret, int format)
{
Lisp_Object o = XCAR (iter);
if (INTEGERP (o))
val = (long) XFASTINT (o);
else if (FLOATP (o))
val = (long) XFLOAT_DATA (o);
else if (CONSP (o))
val = (long) cons_to_long (o);
if (INTEGERP (o) || FLOATP (o) || CONSP (o))
val = cons_to_signed (o, LONG_MIN, LONG_MAX);
else if (STRINGP (o))
{
BLOCK_INPUT;
@ -2266,9 +2256,19 @@ x_fill_property_data (Display *dpy, Lisp_Object data, void *ret, int format)
error ("Wrong type, must be string, number or cons");
if (format == 8)
*d08++ = (char) val;
{
if (CHAR_MIN <= val && val <= CHAR_MAX)
*d08++ = val;
else
error ("Out of 'char' range");
}
else if (format == 16)
*d16++ = (short) val;
{
if (SHRT_MIN <= val && val <= SHRT_MAX)
*d16++ = val;
else
error ("Out of 'short' range");
}
else
*d32++ = val;
}
@ -2352,14 +2352,7 @@ If the value is 0 or the atom is not known, return the empty string. */)
Atom atom;
int had_errors;
if (INTEGERP (value))
atom = (Atom) XUINT (value);
else if (FLOATP (value))
atom = (Atom) XFLOAT_DATA (value);
else if (CONSP (value))
atom = (Atom) cons_to_long (value);
else
error ("Wrong type, value must be number or cons");
CONS_TO_INTEGER (value, Atom, atom);
BLOCK_INPUT;
x_catch_errors (dpy);
@ -2549,17 +2542,8 @@ x_send_client_event (Lisp_Object display, Lisp_Object dest, Lisp_Object from, At
else
error ("DEST as a string must be one of PointerWindow or InputFocus");
}
else if (INTEGERP (dest))
wdest = (Window) XFASTINT (dest);
else if (FLOATP (dest))
wdest = (Window) XFLOAT_DATA (dest);
else if (CONSP (dest))
{
if (! NUMBERP (XCAR (dest)) || ! NUMBERP (XCDR (dest)))
error ("Both car and cdr for DEST must be numbers");
else
wdest = (Window) cons_to_long (dest);
}
else if (INTEGERP (dest) || FLOATP (dest) || CONSP (dest))
CONS_TO_INTEGER (dest, Window, wdest);
else
error ("DEST must be a frame, nil, string, number or cons");