diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 15 | ||||
| -rw-r--r-- | src/alloc.c | 2 | ||||
| -rw-r--r-- | src/buffer.h | 5 | ||||
| -rw-r--r-- | src/character.c | 4 | ||||
| -rw-r--r-- | src/coding.c | 4 | ||||
| -rw-r--r-- | src/doprnt.c | 4 | ||||
| -rw-r--r-- | src/editfns.c | 4 | ||||
| -rw-r--r-- | src/eval.c | 2 | ||||
| -rw-r--r-- | src/fileio.c | 2 | ||||
| -rw-r--r-- | src/lisp.h | 6 |
10 files changed, 37 insertions, 11 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 7fb1479e548..bf81533460a 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,5 +1,20 @@ | |||
| 1 | 2011-06-06 Paul Eggert <eggert@cs.ucla.edu> | 1 | 2011-06-06 Paul Eggert <eggert@cs.ucla.edu> |
| 2 | 2 | ||
| 3 | Check for buffer and string overflow more precisely. | ||
| 4 | * buffer.h (BUF_BYTES_MAX): New macro. | ||
| 5 | * lisp.h (STRING_BYTES_MAX): New macro. | ||
| 6 | * alloc.c (Fmake_string): | ||
| 7 | * character.c (string_escape_byte8): | ||
| 8 | * coding.c (coding_alloc_by_realloc): | ||
| 9 | * doprnt.c (doprnt): | ||
| 10 | * editfns.c (Fformat): | ||
| 11 | * eval.c (verror): | ||
| 12 | Use STRING_BYTES_MAX, not MOST_POSITIVE_FIXNUM, | ||
| 13 | since they may not be the same number. | ||
| 14 | * editfns.c (Finsert_char): | ||
| 15 | * fileio.c (Finsert_file_contents): | ||
| 16 | Likewise for BUF_BYTES_MAX. | ||
| 17 | |||
| 3 | * image.c: Use ptrdiff_t, not int, for sizes. | 18 | * image.c: Use ptrdiff_t, not int, for sizes. |
| 4 | (slurp_file): Switch from int to ptrdiff_t. | 19 | (slurp_file): Switch from int to ptrdiff_t. |
| 5 | All uses changed. | 20 | All uses changed. |
diff --git a/src/alloc.c b/src/alloc.c index 8d0fdd125dc..d9e00c3aeb4 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -2211,7 +2211,7 @@ INIT must be an integer that represents a character. */) | |||
| 2211 | int len = CHAR_STRING (c, str); | 2211 | int len = CHAR_STRING (c, str); |
| 2212 | EMACS_INT string_len = XINT (length); | 2212 | EMACS_INT string_len = XINT (length); |
| 2213 | 2213 | ||
| 2214 | if (string_len > MOST_POSITIVE_FIXNUM / len) | 2214 | if (string_len > STRING_BYTES_MAX / len) |
| 2215 | string_overflow (); | 2215 | string_overflow (); |
| 2216 | nbytes = len * string_len; | 2216 | nbytes = len * string_len; |
| 2217 | val = make_uninit_multibyte_string (string_len, nbytes); | 2217 | val = make_uninit_multibyte_string (string_len, nbytes); |
diff --git a/src/buffer.h b/src/buffer.h index 8c64a24e804..3c91bdfe570 100644 --- a/src/buffer.h +++ b/src/buffer.h | |||
| @@ -306,6 +306,11 @@ do \ | |||
| 306 | } \ | 306 | } \ |
| 307 | while (0) | 307 | while (0) |
| 308 | 308 | ||
| 309 | /* Maximum number of bytes in a buffer. | ||
| 310 | A buffer cannot contain more bytes than a 1-origin fixnum can represent, | ||
| 311 | nor can it be so large that C pointer arithmetic stops working. */ | ||
| 312 | #define BUF_BYTES_MAX min (MOST_POSITIVE_FIXNUM - 1, min (SIZE_MAX, PTRDIFF_MAX)) | ||
| 313 | |||
| 309 | /* Return the address of byte position N in current buffer. */ | 314 | /* Return the address of byte position N in current buffer. */ |
| 310 | 315 | ||
| 311 | #define BYTE_POS_ADDR(n) \ | 316 | #define BYTE_POS_ADDR(n) \ |
diff --git a/src/character.c b/src/character.c index 34e69da9cc5..170952619e7 100644 --- a/src/character.c +++ b/src/character.c | |||
| @@ -838,7 +838,7 @@ string_escape_byte8 (Lisp_Object string) | |||
| 838 | if (multibyte) | 838 | if (multibyte) |
| 839 | { | 839 | { |
| 840 | if ((MOST_POSITIVE_FIXNUM - nchars) / 3 < byte8_count | 840 | if ((MOST_POSITIVE_FIXNUM - nchars) / 3 < byte8_count |
| 841 | || (MOST_POSITIVE_FIXNUM - nbytes) / 2 < byte8_count) | 841 | || (STRING_BYTES_MAX - nbytes) / 2 < byte8_count) |
| 842 | string_overflow (); | 842 | string_overflow (); |
| 843 | 843 | ||
| 844 | /* Convert 2-byte sequence of byte8 chars to 4-byte octal. */ | 844 | /* Convert 2-byte sequence of byte8 chars to 4-byte octal. */ |
| @@ -847,7 +847,7 @@ string_escape_byte8 (Lisp_Object string) | |||
| 847 | } | 847 | } |
| 848 | else | 848 | else |
| 849 | { | 849 | { |
| 850 | if ((MOST_POSITIVE_FIXNUM - nchars) / 3 < byte8_count) | 850 | if ((STRING_BYTES_MAX - nchars) / 3 < byte8_count) |
| 851 | string_overflow (); | 851 | string_overflow (); |
| 852 | 852 | ||
| 853 | /* Convert 1-byte sequence of byte8 chars to 4-byte octal. */ | 853 | /* Convert 1-byte sequence of byte8 chars to 4-byte octal. */ |
diff --git a/src/coding.c b/src/coding.c index 6ccaf354c74..64e8e41a5a1 100644 --- a/src/coding.c +++ b/src/coding.c | |||
| @@ -1071,8 +1071,8 @@ coding_set_destination (struct coding_system *coding) | |||
| 1071 | static void | 1071 | static void |
| 1072 | coding_alloc_by_realloc (struct coding_system *coding, EMACS_INT bytes) | 1072 | coding_alloc_by_realloc (struct coding_system *coding, EMACS_INT bytes) |
| 1073 | { | 1073 | { |
| 1074 | if (coding->dst_bytes >= MOST_POSITIVE_FIXNUM - bytes) | 1074 | if (STRING_BYTES_MAX - coding->dst_bytes < bytes) |
| 1075 | error ("Maximum size of buffer or string exceeded"); | 1075 | string_overflow (); |
| 1076 | coding->destination = (unsigned char *) xrealloc (coding->destination, | 1076 | coding->destination = (unsigned char *) xrealloc (coding->destination, |
| 1077 | coding->dst_bytes + bytes); | 1077 | coding->dst_bytes + bytes); |
| 1078 | coding->dst_bytes += bytes; | 1078 | coding->dst_bytes += bytes; |
diff --git a/src/doprnt.c b/src/doprnt.c index d2abc119912..5ca3ea89be6 100644 --- a/src/doprnt.c +++ b/src/doprnt.c | |||
| @@ -329,7 +329,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format, | |||
| 329 | minlen = atoi (&fmtcpy[1]); | 329 | minlen = atoi (&fmtcpy[1]); |
| 330 | string = va_arg (ap, char *); | 330 | string = va_arg (ap, char *); |
| 331 | tem = strlen (string); | 331 | tem = strlen (string); |
| 332 | if (tem > MOST_POSITIVE_FIXNUM) | 332 | if (tem > STRING_BYTES_MAX) |
| 333 | error ("String for %%s or %%S format is too long"); | 333 | error ("String for %%s or %%S format is too long"); |
| 334 | width = strwidth (string, tem); | 334 | width = strwidth (string, tem); |
| 335 | goto doit1; | 335 | goto doit1; |
| @@ -338,7 +338,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format, | |||
| 338 | doit: | 338 | doit: |
| 339 | /* Coming here means STRING contains ASCII only. */ | 339 | /* Coming here means STRING contains ASCII only. */ |
| 340 | tem = strlen (string); | 340 | tem = strlen (string); |
| 341 | if (tem > MOST_POSITIVE_FIXNUM) | 341 | if (tem > STRING_BYTES_MAX) |
| 342 | error ("Format width or precision too large"); | 342 | error ("Format width or precision too large"); |
| 343 | width = tem; | 343 | width = tem; |
| 344 | doit1: | 344 | doit1: |
diff --git a/src/editfns.c b/src/editfns.c index b961e602e4c..b4ce9a1c571 100644 --- a/src/editfns.c +++ b/src/editfns.c | |||
| @@ -2342,7 +2342,7 @@ from adjoining text, if those properties are sticky. */) | |||
| 2342 | len = CHAR_STRING (XFASTINT (character), str); | 2342 | len = CHAR_STRING (XFASTINT (character), str); |
| 2343 | else | 2343 | else |
| 2344 | str[0] = XFASTINT (character), len = 1; | 2344 | str[0] = XFASTINT (character), len = 1; |
| 2345 | if (MOST_POSITIVE_FIXNUM / len < XINT (count)) | 2345 | if (BUF_BYTES_MAX / len < XINT (count)) |
| 2346 | error ("Maximum buffer size would be exceeded"); | 2346 | error ("Maximum buffer size would be exceeded"); |
| 2347 | n = XINT (count) * len; | 2347 | n = XINT (count) * len; |
| 2348 | if (n <= 0) | 2348 | if (n <= 0) |
| @@ -3589,7 +3589,7 @@ usage: (format STRING &rest OBJECTS) */) | |||
| 3589 | char initial_buffer[4000]; | 3589 | char initial_buffer[4000]; |
| 3590 | char *buf = initial_buffer; | 3590 | char *buf = initial_buffer; |
| 3591 | EMACS_INT bufsize = sizeof initial_buffer; | 3591 | EMACS_INT bufsize = sizeof initial_buffer; |
| 3592 | EMACS_INT max_bufsize = min (MOST_POSITIVE_FIXNUM + 1, SIZE_MAX); | 3592 | EMACS_INT max_bufsize = STRING_BYTES_MAX + 1; |
| 3593 | char *p; | 3593 | char *p; |
| 3594 | Lisp_Object buf_save_value IF_LINT (= {0}); | 3594 | Lisp_Object buf_save_value IF_LINT (= {0}); |
| 3595 | register char *format, *end, *format_start; | 3595 | register char *format, *end, *format_start; |
diff --git a/src/eval.c b/src/eval.c index f8bc0a9f6aa..ef5abac17ae 100644 --- a/src/eval.c +++ b/src/eval.c | |||
| @@ -1994,7 +1994,7 @@ verror (const char *m, va_list ap) | |||
| 1994 | { | 1994 | { |
| 1995 | char buf[4000]; | 1995 | char buf[4000]; |
| 1996 | size_t size = sizeof buf; | 1996 | size_t size = sizeof buf; |
| 1997 | size_t size_max = min (MOST_POSITIVE_FIXNUM + 1, SIZE_MAX); | 1997 | size_t size_max = STRING_BYTES_MAX + 1; |
| 1998 | size_t mlen = strlen (m); | 1998 | size_t mlen = strlen (m); |
| 1999 | char *buffer = buf; | 1999 | char *buffer = buf; |
| 2000 | size_t used; | 2000 | size_t used; |
diff --git a/src/fileio.c b/src/fileio.c index 48dac80a39f..82b31036fb9 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -3248,7 +3248,7 @@ variable `last-coding-system-used' to the coding system actually used. */) | |||
| 3248 | /* Check whether the size is too large or negative, which can happen on a | 3248 | /* Check whether the size is too large or negative, which can happen on a |
| 3249 | platform that allows file sizes greater than the maximum off_t value. */ | 3249 | platform that allows file sizes greater than the maximum off_t value. */ |
| 3250 | if (! not_regular | 3250 | if (! not_regular |
| 3251 | && ! (0 <= st.st_size && st.st_size <= MOST_POSITIVE_FIXNUM)) | 3251 | && ! (0 <= st.st_size && st.st_size <= BUF_BYTES_MAX)) |
| 3252 | error ("Maximum buffer size exceeded"); | 3252 | error ("Maximum buffer size exceeded"); |
| 3253 | 3253 | ||
| 3254 | /* Prevent redisplay optimizations. */ | 3254 | /* Prevent redisplay optimizations. */ |
diff --git a/src/lisp.h b/src/lisp.h index a9e7354f9fc..a46436e718b 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -763,6 +763,12 @@ extern EMACS_INT string_bytes (struct Lisp_String *); | |||
| 763 | 763 | ||
| 764 | #endif /* not GC_CHECK_STRING_BYTES */ | 764 | #endif /* not GC_CHECK_STRING_BYTES */ |
| 765 | 765 | ||
| 766 | /* A string cannot contain more bytes than a fixnum can represent, | ||
| 767 | nor can it be so long that C pointer arithmetic stops working on | ||
| 768 | the string plus a terminating null. */ | ||
| 769 | #define STRING_BYTES_MAX \ | ||
| 770 | min (MOST_POSITIVE_FIXNUM, min (SIZE_MAX, PTRDIFF_MAX) - 1) | ||
| 771 | |||
| 766 | /* Mark STR as a unibyte string. */ | 772 | /* Mark STR as a unibyte string. */ |
| 767 | #define STRING_SET_UNIBYTE(STR) \ | 773 | #define STRING_SET_UNIBYTE(STR) \ |
| 768 | do { if (EQ (STR, empty_multibyte_string)) \ | 774 | do { if (EQ (STR, empty_multibyte_string)) \ |