[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] /srv/bzr/emacs/trunk r104686: Merge: Integer and buffer ov
From: |
Paul Eggert |
Subject: |
[Emacs-diffs] /srv/bzr/emacs/trunk r104686: Merge: Integer and buffer overflow fixes. |
Date: |
Thu, 23 Jun 2011 00:51:45 -0700 |
User-agent: |
Bazaar (2.3.1) |
------------------------------------------------------------
revno: 104686 [merge]
committer: Paul Eggert <address@hidden>
branch nick: trunk
timestamp: Thu 2011-06-23 00:51:45 -0700
message:
Merge: Integer and buffer overflow fixes.
modified:
src/ChangeLog
src/image.c
src/keyboard.h
src/lisp.h
src/lread.c
src/macros.c
src/minibuf.c
src/print.c
=== modified file 'src/ChangeLog'
--- a/src/ChangeLog 2011-06-23 03:35:05 +0000
+++ b/src/ChangeLog 2011-06-23 07:37:31 +0000
@@ -1,3 +1,49 @@
+2011-06-23 Paul Eggert <address@hidden>
+
+ Integer and buffer overflow fixes (Bug#8873).
+
+ * print.c (printchar, strout): Check for string overflow.
+ (PRINTPREPARE, printchar, strout):
+ Don't set size unless allocation succeeds.
+
+ * minibuf.c (read_minibuf_noninteractive): Use ptrdiff_t, not int,
+ for sizes. Check for string overflow more accurately.
+ Simplify newline removal at end; this suppresses a GCC 4.6.0 warning.
+
+ * macros.c: Integer and buffer overflow fixes.
+ * keyboard.h (struct keyboard.kbd_macro_bufsize):
+ * macros.c (Fstart_kbd_macro, store_kbd_macro_char):
+ Use ptrdiff_t, not int, for sizes.
+ Don't increment bufsize until after realloc succeeds.
+ Check for size-calculation overflow.
+ (Fstart_kbd_macro): Use EMACS_INT, not int, for XINT result.
+
+ * lisp.h (DEFVAR_KBOARD): Use offsetof instead of char * finagling.
+
+ * lread.c: Integer overflow fixes.
+ (read_integer): Radix is now EMACS_INT, not int,
+ to improve quality of diagnostics for out-of-range radices.
+ Calculate buffer size correctly for out-of-range radices.
+ (read1): Check for integer overflow in radices, and in
+ read-circle numbers.
+ (read_escape): Avoid int overflow.
+ (Fload, openp, read_buffer_size, read1)
+ (substitute_object_recurse, read_vector, read_list, map_obarray):
+ Use ptrdiff_t, not int, for sizes.
+ (read1): Use EMACS_INT, not int, for sizes.
+ Check for size overflow.
+
+ * image.c (cache_image): Check for size arithmetic overflow.
+
+ * lread.c: Integer overflow issues.
+ (saved_doc_string_size, saved_doc_string_length)
+ (prev_saved_doc_string_size, prev_saved_doc_string_length):
+ Now ptrdiff_t, not int.
+ (read1): Don't assume doc string length fits in int. Check for
+ out-of-range doc string lengths.
+ (read_list): Don't assume file position fits in int.
+ (read_escape): Check for hex character overflow.
+
2011-06-22 Leo Liu <address@hidden>
* minibuf.c (Fcompleting_read_default, Vcompleting_read_function):
=== modified file 'src/image.c'
--- a/src/image.c 2011-06-22 16:01:00 +0000
+++ b/src/image.c 2011-06-23 00:46:41 +0000
@@ -1836,6 +1836,8 @@
/* If no free slot found, maybe enlarge c->images. */
if (i == c->used && c->used == c->size)
{
+ if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *c->images / 2 < c->size)
+ memory_full (SIZE_MAX);
c->size *= 2;
c->images = (struct image **) xrealloc (c->images,
c->size * sizeof *c->images);
=== modified file 'src/keyboard.h'
--- a/src/keyboard.h 2011-06-11 21:31:32 +0000
+++ b/src/keyboard.h 2011-06-23 06:31:41 +0000
@@ -123,7 +123,7 @@
Lisp_Object *kbd_macro_end;
/* Allocated size of kbd_macro_buffer. */
- int kbd_macro_bufsize;
+ ptrdiff_t kbd_macro_bufsize;
/* Last anonymous kbd macro defined. */
Lisp_Object KBOARD_INTERNAL_FIELD (Vlast_kbd_macro);
=== modified file 'src/lisp.h'
--- a/src/lisp.h 2011-06-22 06:16:16 +0000
+++ b/src/lisp.h 2011-06-23 05:35:51 +0000
@@ -1980,10 +1980,7 @@
#define DEFVAR_KBOARD(lname, vname, doc) \
do { \
static struct Lisp_Kboard_Objfwd ko_fwd; \
- defvar_kboard (&ko_fwd, \
- lname, \
- (int)((char *)(¤t_kboard->vname ## _) \
- - (char *)current_kboard)); \
+ defvar_kboard (&ko_fwd, lname, offsetof (KBOARD, vname ## _)); \
} while (0)
=== modified file 'src/lread.c'
--- a/src/lread.c 2011-06-20 06:11:36 +0000
+++ b/src/lread.c 2011-06-23 05:41:40 +0000
@@ -120,9 +120,9 @@
/* This contains the last string skipped with address@hidden */
static char *saved_doc_string;
/* Length of buffer allocated in saved_doc_string. */
-static int saved_doc_string_size;
+static ptrdiff_t saved_doc_string_size;
/* Length of actual data in saved_doc_string. */
-static int saved_doc_string_length;
+static ptrdiff_t saved_doc_string_length;
/* This is the file position that string came from. */
static file_offset saved_doc_string_position;
@@ -131,9 +131,9 @@
is put in saved_doc_string. */
static char *prev_saved_doc_string;
/* Length of buffer allocated in prev_saved_doc_string. */
-static int prev_saved_doc_string_size;
+static ptrdiff_t prev_saved_doc_string_size;
/* Length of actual data in prev_saved_doc_string. */
-static int prev_saved_doc_string_length;
+static ptrdiff_t prev_saved_doc_string_length;
/* This is the file position that string came from. */
static file_offset prev_saved_doc_string_position;
@@ -1069,9 +1069,9 @@
/* Avoid weird lossage with null string as arg,
since it would try to load a directory as a Lisp file */
- if (SCHARS (file) > 0)
+ if (SBYTES (file) > 0)
{
- int size = SBYTES (file);
+ ptrdiff_t size = SBYTES (file);
found = Qnil;
GCPRO2 (file, found);
@@ -1472,7 +1472,7 @@
for (tail = NILP (suffixes) ? Fcons (empty_unibyte_string, Qnil) :
suffixes;
CONSP (tail); tail = XCDR (tail))
{
- int lsuffix = SBYTES (XCAR (tail));
+ ptrdiff_t lsuffix = SBYTES (XCAR (tail));
Lisp_Object handler;
int exists;
@@ -2037,7 +2037,7 @@
Fmake_string (make_number (1), make_number (c)));
}
-static int read_buffer_size;
+static ptrdiff_t read_buffer_size;
static char *read_buffer;
/* Read a \-escape sequence, assuming we already read the `\'.
@@ -2208,7 +2208,9 @@
UNREAD (c);
break;
}
- count++;
+ if (MAX_CHAR < i)
+ error ("Hex character out of range: \\x%x...", i);
+ count += count < 3;
}
if (count < 3 && i >= 0x80)
@@ -2236,10 +2238,7 @@
else if (c >= 'a' && c <= 'f') i = (i << 4) + (c - 'a') + 10;
else if (c >= 'A' && c <= 'F') i = (i << 4) + (c - 'A') + 10;
else
- {
- error ("Non-hex digit used for Unicode escape");
- break;
- }
+ error ("Non-hex digit used for Unicode escape");
}
if (i > 0x10FFFF)
error ("Non-Unicode character: 0x%x", i);
@@ -2278,10 +2277,12 @@
range. */
static Lisp_Object
-read_integer (Lisp_Object readcharfun, int radix)
+read_integer (Lisp_Object readcharfun, EMACS_INT radix)
{
- /* Room for sign, leading 0, other digits, trailing null byte. */
- char buf[1 + 1 + sizeof (uintmax_t) * CHAR_BIT + 1];
+ /* Room for sign, leading 0, other digits, trailing null byte.
+ Also, room for invalid syntax diagnostic. */
+ char buf[max (1 + 1 + sizeof (uintmax_t) * CHAR_BIT + 1,
+ sizeof "integer, radix " + INT_STRLEN_BOUND (EMACS_INT))];
int valid = -1; /* 1 if valid, 0 if not, -1 if incomplete. */
@@ -2333,7 +2334,7 @@
if (! valid)
{
- sprintf (buf, "integer, radix %d", radix);
+ sprintf (buf, "integer, radix %"pI"d", radix);
invalid_syntax (buf);
}
@@ -2471,7 +2472,7 @@
if (c == '[')
{
Lisp_Object tmp;
- int depth, size;
+ EMACS_INT depth, size;
tmp = read_vector (readcharfun, 0);
if (!INTEGERP (AREF (tmp, 0)))
@@ -2497,7 +2498,7 @@
if (c == '"')
{
Lisp_Object tmp, val;
- int size_in_chars
+ EMACS_INT size_in_chars
= ((XFASTINT (length) + BOOL_VECTOR_BITS_PER_CHAR - 1)
/ BOOL_VECTOR_BITS_PER_CHAR);
@@ -2569,13 +2570,16 @@
and function definitions. */
if (c == '@')
{
- int i, nskip = 0;
+ enum { extra = 100 };
+ ptrdiff_t i, nskip = 0;
load_each_byte = 1;
/* Read a decimal integer. */
while ((c = READCHAR) >= 0
&& c >= '0' && c <= '9')
{
+ if ((STRING_BYTES_BOUND - extra) / 10 <= nskip)
+ string_overflow ();
nskip *= 10;
nskip += c - '0';
}
@@ -2594,9 +2598,9 @@
with prev_saved_doc_string, so we save two strings. */
{
char *temp = saved_doc_string;
- int temp_size = saved_doc_string_size;
+ ptrdiff_t temp_size = saved_doc_string_size;
file_offset temp_pos = saved_doc_string_position;
- int temp_len = saved_doc_string_length;
+ ptrdiff_t temp_len = saved_doc_string_length;
saved_doc_string = prev_saved_doc_string;
saved_doc_string_size = prev_saved_doc_string_size;
@@ -2611,12 +2615,12 @@
if (saved_doc_string_size == 0)
{
- saved_doc_string_size = nskip + 100;
+ saved_doc_string_size = nskip + extra;
saved_doc_string = (char *) xmalloc (saved_doc_string_size);
}
if (nskip > saved_doc_string_size)
{
- saved_doc_string_size = nskip + 100;
+ saved_doc_string_size = nskip + extra;
saved_doc_string = (char *) xrealloc (saved_doc_string,
saved_doc_string_size);
}
@@ -2661,49 +2665,60 @@
/* Reader forms that can reuse previously read objects. */
if (c >= '0' && c <= '9')
{
- int n = 0;
+ EMACS_INT n = 0;
Lisp_Object tem;
/* Read a non-negative integer. */
while (c >= '0' && c <= '9')
{
- n *= 10;
- n += c - '0';
+ if (MOST_POSITIVE_FIXNUM / 10 < n
+ || MOST_POSITIVE_FIXNUM < n * 10 + c - '0')
+ n = MOST_POSITIVE_FIXNUM + 1;
+ else
+ n = n * 10 + c - '0';
c = READCHAR;
}
- /* #n=object returns object, but associates it with n for #n#. */
- if (c == '=' && !NILP (Vread_circle))
- {
- /* Make a placeholder for #n# to use temporarily */
- Lisp_Object placeholder;
- Lisp_Object cell;
-
- placeholder = Fcons (Qnil, Qnil);
- cell = Fcons (make_number (n), placeholder);
- read_objects = Fcons (cell, read_objects);
-
- /* Read the object itself. */
- tem = read0 (readcharfun);
-
- /* Now put it everywhere the placeholder was... */
- substitute_object_in_subtree (tem, placeholder);
-
- /* ...and #n# will use the real value from now on. */
- Fsetcdr (cell, tem);
-
- return tem;
- }
- /* #n# returns a previously read object. */
- if (c == '#' && !NILP (Vread_circle))
- {
- tem = Fassq (make_number (n), read_objects);
- if (CONSP (tem))
- return XCDR (tem);
- /* Fall through to error message. */
- }
- else if (c == 'r' || c == 'R')
- return read_integer (readcharfun, n);
-
+
+ if (n <= MOST_POSITIVE_FIXNUM)
+ {
+ if (c == 'r' || c == 'R')
+ return read_integer (readcharfun, n);
+
+ if (! NILP (Vread_circle))
+ {
+ /* #n=object returns object, but associates it with
+ n for #n#. */
+ if (c == '=')
+ {
+ /* Make a placeholder for #n# to use temporarily */
+ Lisp_Object placeholder;
+ Lisp_Object cell;
+
+ placeholder = Fcons (Qnil, Qnil);
+ cell = Fcons (make_number (n), placeholder);
+ read_objects = Fcons (cell, read_objects);
+
+ /* Read the object itself. */
+ tem = read0 (readcharfun);
+
+ /* Now put it everywhere the placeholder was... */
+ substitute_object_in_subtree (tem, placeholder);
+
+ /* ...and #n# will use the real value from now on. */
+ Fsetcdr (cell, tem);
+
+ return tem;
+ }
+
+ /* #n# returns a previously read object. */
+ if (c == '#')
+ {
+ tem = Fassq (make_number (n), read_objects);
+ if (CONSP (tem))
+ return XCDR (tem);
+ }
+ }
+ }
/* Fall through to error message. */
}
else if (c == 'x' || c == 'X')
@@ -2846,14 +2861,16 @@
a single-byte character. */
int force_singlebyte = 0;
int cancel = 0;
- int nchars = 0;
+ ptrdiff_t nchars = 0;
while ((ch = READCHAR) >= 0
&& ch != '\"')
{
if (end - p < MAX_MULTIBYTE_LENGTH)
{
- int offset = p - read_buffer;
+ ptrdiff_t offset = p - read_buffer;
+ if (min (PTRDIFF_MAX, SIZE_MAX) / 2 < read_buffer_size)
+ memory_full (SIZE_MAX);
read_buffer = (char *) xrealloc (read_buffer,
read_buffer_size *= 2);
p = read_buffer + offset;
@@ -2996,7 +3013,9 @@
{
if (end - p < MAX_MULTIBYTE_LENGTH)
{
- int offset = p - read_buffer;
+ ptrdiff_t offset = p - read_buffer;
+ if (min (PTRDIFF_MAX, SIZE_MAX) / 2 < read_buffer_size)
+ memory_full (SIZE_MAX);
read_buffer = (char *) xrealloc (read_buffer,
read_buffer_size *= 2);
p = read_buffer + offset;
@@ -3023,7 +3042,9 @@
if (p == end)
{
- int offset = p - read_buffer;
+ ptrdiff_t offset = p - read_buffer;
+ if (min (PTRDIFF_MAX, SIZE_MAX) / 2 < read_buffer_size)
+ memory_full (SIZE_MAX);
read_buffer = (char *) xrealloc (read_buffer,
read_buffer_size *= 2);
p = read_buffer + offset;
@@ -3135,7 +3156,7 @@
{
case Lisp_Vectorlike:
{
- int i, length = 0;
+ ptrdiff_t i, length = 0;
if (BOOL_VECTOR_P (subtree))
return subtree; /* No sub-objects anyway. */
else if (CHAR_TABLE_P (subtree) || SUB_CHAR_TABLE_P (subtree)
@@ -3358,8 +3379,7 @@
static Lisp_Object
read_vector (Lisp_Object readcharfun, int bytecodeflag)
{
- register int i;
- register int size;
+ ptrdiff_t i, size;
register Lisp_Object *ptr;
register Lisp_Object tem, item, vector;
register struct Lisp_Cons *otem;
@@ -3528,15 +3548,15 @@
doc string, caller must make it
multibyte. */
- int pos = XINT (XCDR (val));
+ EMACS_INT pos = XINT (XCDR (val));
/* Position is negative for user variables. */
if (pos < 0) pos = -pos;
if (pos >= saved_doc_string_position
&& pos < (saved_doc_string_position
+ saved_doc_string_length))
{
- int start = pos - saved_doc_string_position;
- int from, to;
+ ptrdiff_t start = pos - saved_doc_string_position;
+ ptrdiff_t from, to;
/* Process quoting with ^A,
and find the end of the string,
@@ -3567,8 +3587,9 @@
&& pos < (prev_saved_doc_string_position
+ prev_saved_doc_string_length))
{
- int start = pos - prev_saved_doc_string_position;
- int from, to;
+ ptrdiff_t start =
+ pos - prev_saved_doc_string_position;
+ ptrdiff_t from, to;
/* Process quoting with ^A,
and find the end of the string,
@@ -3891,7 +3912,7 @@
void
map_obarray (Lisp_Object obarray, void (*fn) (Lisp_Object, Lisp_Object),
Lisp_Object arg)
{
- register int i;
+ ptrdiff_t i;
register Lisp_Object tail;
CHECK_VECTOR (obarray);
for (i = ASIZE (obarray) - 1; i >= 0; i--)
@@ -3991,7 +4012,7 @@
#endif /* NOTDEF */
/* Define an "integer variable"; a symbol whose value is forwarded to a
- C variable of type int. Sample call (munged w "xx" to fool make-docfile):
+ C variable of type EMACS_INT. Sample call (with "xx" to fool make-docfile):
DEFxxVAR_INT ("emacs-priority", &emacs_priority, "Documentation"); */
void
defvar_int (struct Lisp_Intfwd *i_fwd,
=== modified file 'src/macros.c'
--- a/src/macros.c 2011-04-14 05:04:02 +0000
+++ b/src/macros.c 2011-06-23 06:31:41 +0000
@@ -71,10 +71,10 @@
{
if (current_kboard->kbd_macro_bufsize > 200)
{
+ current_kboard->kbd_macro_buffer
+ = (Lisp_Object *)xrealloc (current_kboard->kbd_macro_buffer,
+ 30 * sizeof (Lisp_Object));
current_kboard->kbd_macro_bufsize = 30;
- current_kboard->kbd_macro_buffer
- = (Lisp_Object *)xrealloc (current_kboard->kbd_macro_buffer,
- 30 * sizeof (Lisp_Object));
}
current_kboard->kbd_macro_ptr = current_kboard->kbd_macro_buffer;
current_kboard->kbd_macro_end = current_kboard->kbd_macro_buffer;
@@ -82,7 +82,8 @@
}
else
{
- int i, len;
+ ptrdiff_t i;
+ EMACS_INT len;
int cvt;
/* Check the type of last-kbd-macro in case Lisp code changed it. */
@@ -94,10 +95,13 @@
has put another macro there. */
if (current_kboard->kbd_macro_bufsize < len + 30)
{
+ if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (Lisp_Object) - 30
+ < current_kboard->kbd_macro_bufsize)
+ memory_full (SIZE_MAX);
+ current_kboard->kbd_macro_buffer
+ = (Lisp_Object *)xrealloc (current_kboard->kbd_macro_buffer,
+ (len + 30) * sizeof (Lisp_Object));
current_kboard->kbd_macro_bufsize = len + 30;
- current_kboard->kbd_macro_buffer
- = (Lisp_Object *)xrealloc (current_kboard->kbd_macro_buffer,
- (len + 30) * sizeof (Lisp_Object));
}
/* Must convert meta modifier when copying string to vector. */
@@ -191,14 +195,17 @@
{
if (kb->kbd_macro_ptr - kb->kbd_macro_buffer == kb->kbd_macro_bufsize)
{
- int ptr_offset, end_offset, nbytes;
+ ptrdiff_t ptr_offset, end_offset, nbytes;
ptr_offset = kb->kbd_macro_ptr - kb->kbd_macro_buffer;
end_offset = kb->kbd_macro_end - kb->kbd_macro_buffer;
- kb->kbd_macro_bufsize *= 2;
- nbytes = kb->kbd_macro_bufsize * sizeof *kb->kbd_macro_buffer;
+ if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *kb->kbd_macro_buffer / 2
+ < kb->kbd_macro_bufsize)
+ memory_full (SIZE_MAX);
+ nbytes = kb->kbd_macro_bufsize * 2 * sizeof *kb->kbd_macro_buffer;
kb->kbd_macro_buffer
= (Lisp_Object *) xrealloc (kb->kbd_macro_buffer, nbytes);
+ kb->kbd_macro_bufsize *= 2;
kb->kbd_macro_ptr = kb->kbd_macro_buffer + ptr_offset;
kb->kbd_macro_end = kb->kbd_macro_buffer + end_offset;
}
=== modified file 'src/minibuf.c'
--- a/src/minibuf.c 2011-06-23 03:35:05 +0000
+++ b/src/minibuf.c 2011-06-23 07:37:31 +0000
@@ -236,7 +236,7 @@
Lisp_Object defalt,
int allow_props, int inherit_input_method)
{
- size_t size, len;
+ ptrdiff_t size, len;
char *line, *s;
Lisp_Object val;
@@ -246,12 +246,12 @@
val = Qnil;
size = 100;
len = 0;
- line = (char *) xmalloc (size * sizeof *line);
+ line = (char *) xmalloc (size);
while ((s = fgets (line + len, size - len, stdin)) != NULL
&& (len = strlen (line),
len == size - 1 && line[len - 1] != '\n'))
{
- if ((size_t) -1 / 2 < size)
+ if (STRING_BYTES_BOUND / 2 < size)
memory_full (SIZE_MAX);
size *= 2;
line = (char *) xrealloc (line, size);
@@ -259,11 +259,9 @@
if (s)
{
- len = strlen (line);
-
- if (len > 0 && line[len - 1] == '\n')
- line[--len] = '\0';
-
+ char *nl = strchr (line, '\n');
+ if (nl)
+ *nl = '\0';
val = build_string (line);
xfree (line);
}
=== modified file 'src/print.c'
--- a/src/print.c 2011-06-08 21:43:46 +0000
+++ b/src/print.c 2011-06-23 07:33:28 +0000
@@ -159,8 +159,9 @@
} \
else \
{ \
- print_buffer_size = 1000; \
- print_buffer = (char *) xmalloc (print_buffer_size);
\
+ ptrdiff_t new_size = 1000; \
+ print_buffer = (char *) xmalloc (new_size); \
+ print_buffer_size = new_size; \
free_print_buffer = 1; \
} \
print_buffer_pos = 0; \
@@ -235,9 +236,15 @@
if (NILP (fun))
{
- if (print_buffer_pos_byte + len >= print_buffer_size)
- print_buffer = (char *) xrealloc (print_buffer,
- print_buffer_size *= 2);
+ if (print_buffer_size - len <= print_buffer_pos_byte)
+ {
+ ptrdiff_t new_size;
+ if (STRING_BYTES_BOUND / 2 < print_buffer_size)
+ string_overflow ();
+ new_size = print_buffer_size * 2;
+ print_buffer = (char *) xrealloc (print_buffer, new_size);
+ print_buffer_size = new_size;
+ }
memcpy (print_buffer + print_buffer_pos_byte, str, len);
print_buffer_pos += 1;
print_buffer_pos_byte += len;
@@ -280,11 +287,14 @@
if (NILP (printcharfun))
{
- if (print_buffer_pos_byte + size_byte > print_buffer_size)
+ if (print_buffer_size - size_byte < print_buffer_pos_byte)
{
- print_buffer_size = print_buffer_size * 2 + size_byte;
- print_buffer = (char *) xrealloc (print_buffer,
- print_buffer_size);
+ ptrdiff_t new_size;
+ if (STRING_BYTES_BOUND / 2 - size_byte < print_buffer_size)
+ string_overflow ();
+ new_size = print_buffer_size * 2 + size_byte;
+ print_buffer = (char *) xrealloc (print_buffer, new_size);
+ print_buffer_size = new_size;
}
memcpy (print_buffer + print_buffer_pos_byte, ptr, size_byte);
print_buffer_pos += size;
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Emacs-diffs] /srv/bzr/emacs/trunk r104686: Merge: Integer and buffer overflow fixes.,
Paul Eggert <=