diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 48 | ||||
| -rw-r--r-- | src/Makefile.in | 2 | ||||
| -rw-r--r-- | src/callint.c | 7 | ||||
| -rw-r--r-- | src/character.c | 2 | ||||
| -rw-r--r-- | src/charset.c | 10 | ||||
| -rw-r--r-- | src/coding.c | 4 | ||||
| -rw-r--r-- | src/deps.mk | 4 | ||||
| -rw-r--r-- | src/doprnt.c | 106 | ||||
| -rw-r--r-- | src/eval.c | 37 | ||||
| -rw-r--r-- | src/font.c | 6 | ||||
| -rw-r--r-- | src/lisp.h | 3 | ||||
| -rw-r--r-- | src/makefile.w32-in | 1 | ||||
| -rw-r--r-- | src/xdisp.c | 18 |
13 files changed, 165 insertions, 83 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 0067163edbf..831fb6afcd0 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,5 +1,53 @@ | |||
| 1 | 2011-04-23 Eli Zaretskii <eliz@gnu.org> | 1 | 2011-04-23 Eli Zaretskii <eliz@gnu.org> |
| 2 | 2 | ||
| 3 | Fix doprnt so it could be used again safely in `verror'. (Bug#8435) | ||
| 4 | * doprnt.c: Include limits.h. | ||
| 5 | (SIZE_MAX): New macro. | ||
| 6 | (doprnt): Return a size_t value. 2nd arg is now size_t. Many | ||
| 7 | local variables are now size_t instead of int or unsigned. | ||
| 8 | Improve overflow protection. Support `l' modifier for integer | ||
| 9 | conversions. Support %l conversion. Don't assume an EMACS_INT | ||
| 10 | argument for integer conversions and for %c. | ||
| 11 | |||
| 12 | * lisp.h (doprnt): Restore prototype. | ||
| 13 | |||
| 14 | * makefile.w32-in ($(BLD)/callint.$(O)): Depend on | ||
| 15 | $(SRC)/character.h. | ||
| 16 | |||
| 17 | * Makefile.in (base_obj): Add back doprnt.o. | ||
| 18 | |||
| 19 | * deps.mk (doprnt.o): Add back prerequisites. | ||
| 20 | (callint.o): Depend on character.h. | ||
| 21 | |||
| 22 | * eval.c (internal_lisp_condition_case): Include the handler | ||
| 23 | representation in the error message. | ||
| 24 | (verror): Call doprnt instead of vsnprintf. Fix an off-by-one bug | ||
| 25 | when breaking from the loop. | ||
| 26 | |||
| 27 | * xdisp.c (vmessage): Call doprnt instead of vsnprintf. | ||
| 28 | |||
| 29 | * callint.c (Fcall_interactively): When displaying error message | ||
| 30 | about invalid control letter, pass the character's codepoint, not | ||
| 31 | a pointer to its multibyte form. Improve display of the character | ||
| 32 | in octal and display also its hex code. | ||
| 33 | |||
| 34 | * character.c (char_string): Use %x to display the (unsigned) | ||
| 35 | codepoint of an invalid character, to avoid displaying a bogus | ||
| 36 | negative value. | ||
| 37 | |||
| 38 | * font.c (check_otf_features): Pass SDATA of SYMBOL_NAME to | ||
| 39 | `error', not SYMBOL_NAME itself. | ||
| 40 | |||
| 41 | * coding.c (Fencode_sjis_char, Fencode_big5_char): Use %c for | ||
| 42 | character arguments to `error'. | ||
| 43 | |||
| 44 | * charset.c (check_iso_charset_parameter): Fix incorrect argument | ||
| 45 | to `error' in error message about FINAL_CHAR argument. Make sure | ||
| 46 | FINAL_CHAR is a character, and use %c when it is passed as | ||
| 47 | argument to `error'. | ||
| 48 | |||
| 49 | 2011-04-23 Eli Zaretskii <eliz@gnu.org> | ||
| 50 | |||
| 3 | * s/ms-w32.h (localtime): Redirect to sys_localtime. | 51 | * s/ms-w32.h (localtime): Redirect to sys_localtime. |
| 4 | 52 | ||
| 5 | * w32.c: Include <time.h>. | 53 | * w32.c: Include <time.h>. |
diff --git a/src/Makefile.in b/src/Makefile.in index 154d6abba4e..e1195968f7f 100644 --- a/src/Makefile.in +++ b/src/Makefile.in | |||
| @@ -354,7 +354,7 @@ base_obj = dispnew.o frame.o scroll.o xdisp.o menu.o $(XMENU_OBJ) window.o \ | |||
| 354 | syntax.o $(UNEXEC_OBJ) bytecode.o \ | 354 | syntax.o $(UNEXEC_OBJ) bytecode.o \ |
| 355 | process.o gnutls.o callproc.o \ | 355 | process.o gnutls.o callproc.o \ |
| 356 | region-cache.o sound.o atimer.o \ | 356 | region-cache.o sound.o atimer.o \ |
| 357 | intervals.o textprop.o composite.o xml.o \ | 357 | doprnt.o intervals.o textprop.o composite.o xml.o \ |
| 358 | $(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) | 358 | $(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) |
| 359 | obj = $(base_obj) $(NS_OBJC_OBJ) | 359 | obj = $(base_obj) $(NS_OBJC_OBJ) |
| 360 | 360 | ||
diff --git a/src/callint.c b/src/callint.c index e5ec3d7d931..cddd92c8a94 100644 --- a/src/callint.c +++ b/src/callint.c | |||
| @@ -27,6 +27,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 27 | #include "keyboard.h" | 27 | #include "keyboard.h" |
| 28 | #include "window.h" | 28 | #include "window.h" |
| 29 | #include "keymap.h" | 29 | #include "keymap.h" |
| 30 | #include "character.h" | ||
| 30 | 31 | ||
| 31 | Lisp_Object Qminus, Qplus; | 32 | Lisp_Object Qminus, Qplus; |
| 32 | Lisp_Object Qcall_interactively; | 33 | Lisp_Object Qcall_interactively; |
| @@ -786,8 +787,10 @@ invoke it. If KEYS is omitted or nil, the return value of | |||
| 786 | if anyone tries to define one here. */ | 787 | if anyone tries to define one here. */ |
| 787 | case '+': | 788 | case '+': |
| 788 | default: | 789 | default: |
| 789 | error ("Invalid control letter `%c' (%03o) in interactive calling string", | 790 | error ("Invalid control letter `%c' (#o%03o, #x%04x) in interactive calling string", |
| 790 | *tem, (unsigned char) *tem); | 791 | STRING_CHAR ((unsigned char *) tem), |
| 792 | (unsigned) STRING_CHAR ((unsigned char *) tem), | ||
| 793 | (unsigned) STRING_CHAR ((unsigned char *) tem)); | ||
| 791 | } | 794 | } |
| 792 | 795 | ||
| 793 | if (varies[i] == 0) | 796 | if (varies[i] == 0) |
diff --git a/src/character.c b/src/character.c index 84eddeb2fc2..4087e8984d0 100644 --- a/src/character.c +++ b/src/character.c | |||
| @@ -156,7 +156,7 @@ char_string (unsigned int c, unsigned char *p) | |||
| 156 | bytes = BYTE8_STRING (c, p); | 156 | bytes = BYTE8_STRING (c, p); |
| 157 | } | 157 | } |
| 158 | else | 158 | else |
| 159 | error ("Invalid character: %d", c); | 159 | error ("Invalid character: %x", c); |
| 160 | 160 | ||
| 161 | return bytes; | 161 | return bytes; |
| 162 | } | 162 | } |
diff --git a/src/charset.c b/src/charset.c index c4699dcb0a7..e7435c292e2 100644 --- a/src/charset.c +++ b/src/charset.c | |||
| @@ -1436,7 +1436,7 @@ check_iso_charset_parameter (Lisp_Object dimension, Lisp_Object chars, Lisp_Obje | |||
| 1436 | { | 1436 | { |
| 1437 | CHECK_NATNUM (dimension); | 1437 | CHECK_NATNUM (dimension); |
| 1438 | CHECK_NATNUM (chars); | 1438 | CHECK_NATNUM (chars); |
| 1439 | CHECK_NATNUM (final_char); | 1439 | CHECK_CHARACTER (final_char); |
| 1440 | 1440 | ||
| 1441 | if (XINT (dimension) > 3) | 1441 | if (XINT (dimension) > 3) |
| 1442 | error ("Invalid DIMENSION %"pEd", it should be 1, 2, or 3", | 1442 | error ("Invalid DIMENSION %"pEd", it should be 1, 2, or 3", |
| @@ -1444,12 +1444,8 @@ check_iso_charset_parameter (Lisp_Object dimension, Lisp_Object chars, Lisp_Obje | |||
| 1444 | if (XINT (chars) != 94 && XINT (chars) != 96) | 1444 | if (XINT (chars) != 94 && XINT (chars) != 96) |
| 1445 | error ("Invalid CHARS %"pEd", it should be 94 or 96", XINT (chars)); | 1445 | error ("Invalid CHARS %"pEd", it should be 94 or 96", XINT (chars)); |
| 1446 | if (XINT (final_char) < '0' || XINT (final_char) > '~') | 1446 | if (XINT (final_char) < '0' || XINT (final_char) > '~') |
| 1447 | { | 1447 | error ("Invalid FINAL-CHAR %c, it should be `0'..`~'", |
| 1448 | unsigned char str[MAX_MULTIBYTE_LENGTH + 1]; | 1448 | (int)XINT (final_char)); |
| 1449 | int len = CHAR_STRING (XINT (chars), str); | ||
| 1450 | str[len] = '\0'; | ||
| 1451 | error ("Invalid FINAL-CHAR %s, it should be `0'..`~'", str); | ||
| 1452 | } | ||
| 1453 | } | 1449 | } |
| 1454 | 1450 | ||
| 1455 | 1451 | ||
diff --git a/src/coding.c b/src/coding.c index b49070e5e16..221ada51158 100644 --- a/src/coding.c +++ b/src/coding.c | |||
| @@ -9071,7 +9071,7 @@ Return the corresponding code in SJIS. */) | |||
| 9071 | charset_list = CODING_ATTR_CHARSET_LIST (attrs); | 9071 | charset_list = CODING_ATTR_CHARSET_LIST (attrs); |
| 9072 | charset = char_charset (c, charset_list, &code); | 9072 | charset = char_charset (c, charset_list, &code); |
| 9073 | if (code == CHARSET_INVALID_CODE (charset)) | 9073 | if (code == CHARSET_INVALID_CODE (charset)) |
| 9074 | error ("Can't encode by shift_jis encoding: %d", c); | 9074 | error ("Can't encode by shift_jis encoding: %c", c); |
| 9075 | JIS_TO_SJIS (code); | 9075 | JIS_TO_SJIS (code); |
| 9076 | 9076 | ||
| 9077 | return make_number (code); | 9077 | return make_number (code); |
| @@ -9142,7 +9142,7 @@ Return the corresponding character code in Big5. */) | |||
| 9142 | charset_list = CODING_ATTR_CHARSET_LIST (attrs); | 9142 | charset_list = CODING_ATTR_CHARSET_LIST (attrs); |
| 9143 | charset = char_charset (c, charset_list, &code); | 9143 | charset = char_charset (c, charset_list, &code); |
| 9144 | if (code == CHARSET_INVALID_CODE (charset)) | 9144 | if (code == CHARSET_INVALID_CODE (charset)) |
| 9145 | error ("Can't encode by Big5 encoding: %d", c); | 9145 | error ("Can't encode by Big5 encoding: %c", c); |
| 9146 | 9146 | ||
| 9147 | return make_number (code); | 9147 | return make_number (code); |
| 9148 | } | 9148 | } |
diff --git a/src/deps.mk b/src/deps.mk index 2df1577ef78..8d0e0e69589 100644 --- a/src/deps.mk +++ b/src/deps.mk | |||
| @@ -44,7 +44,8 @@ buffer.o: buffer.c buffer.h region-cache.h commands.h window.h \ | |||
| 44 | $(INTERVALS_H) blockinput.h atimer.h systime.h character.h ../lib/unistd.h \ | 44 | $(INTERVALS_H) blockinput.h atimer.h systime.h character.h ../lib/unistd.h \ |
| 45 | indent.h keyboard.h coding.h keymap.h frame.h lisp.h globals.h $(config_h) | 45 | indent.h keyboard.h coding.h keymap.h frame.h lisp.h globals.h $(config_h) |
| 46 | callint.o: callint.c window.h commands.h buffer.h keymap.h globals.h msdos.h \ | 46 | callint.o: callint.c window.h commands.h buffer.h keymap.h globals.h msdos.h \ |
| 47 | keyboard.h dispextern.h systime.h coding.h composite.h lisp.h $(config_h) | 47 | keyboard.h dispextern.h systime.h coding.h composite.h lisp.h \ |
| 48 | character.h $(config_h) | ||
| 48 | callproc.o: callproc.c epaths.h buffer.h commands.h lisp.h $(config_h) \ | 49 | callproc.o: callproc.c epaths.h buffer.h commands.h lisp.h $(config_h) \ |
| 49 | process.h systty.h syssignal.h character.h coding.h ccl.h msdos.h \ | 50 | process.h systty.h syssignal.h character.h coding.h ccl.h msdos.h \ |
| 50 | composite.h w32.h blockinput.h atimer.h systime.h frame.h termhooks.h \ | 51 | composite.h w32.h blockinput.h atimer.h systime.h frame.h termhooks.h \ |
| @@ -82,6 +83,7 @@ dispnew.o: dispnew.c systime.h commands.h process.h frame.h coding.h \ | |||
| 82 | # doc.o's dependency on buildobj.h is in src/Makefile.in. | 83 | # doc.o's dependency on buildobj.h is in src/Makefile.in. |
| 83 | doc.o: doc.c lisp.h $(config_h) buffer.h keyboard.h keymap.h \ | 84 | doc.o: doc.c lisp.h $(config_h) buffer.h keyboard.h keymap.h \ |
| 84 | character.h systime.h coding.h composite.h ../lib/unistd.h globals.h | 85 | character.h systime.h coding.h composite.h ../lib/unistd.h globals.h |
| 86 | doprnt.o: doprnt.c character.h lisp.h globals.h ../lib/unistd.h $(config_h) | ||
| 85 | dosfns.o: buffer.h termchar.h termhooks.h frame.h blockinput.h window.h \ | 87 | dosfns.o: buffer.h termchar.h termhooks.h frame.h blockinput.h window.h \ |
| 86 | msdos.h dosfns.h dispextern.h charset.h coding.h atimer.h systime.h \ | 88 | msdos.h dosfns.h dispextern.h charset.h coding.h atimer.h systime.h \ |
| 87 | lisp.h $(config_h) | 89 | lisp.h $(config_h) |
diff --git a/src/doprnt.c b/src/doprnt.c index 36eb272caae..f182529b801 100644 --- a/src/doprnt.c +++ b/src/doprnt.c | |||
| @@ -30,6 +30,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 30 | 30 | ||
| 31 | #include <unistd.h> | 31 | #include <unistd.h> |
| 32 | 32 | ||
| 33 | #include <limits.h> | ||
| 34 | #ifndef SIZE_MAX | ||
| 35 | # define SIZE_MAX ((size_t) -1) | ||
| 36 | #endif | ||
| 37 | |||
| 33 | #include "lisp.h" | 38 | #include "lisp.h" |
| 34 | 39 | ||
| 35 | /* Since we use the macro CHAR_HEAD_P, we have to include this, but | 40 | /* Since we use the macro CHAR_HEAD_P, we have to include this, but |
| @@ -51,8 +56,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 51 | String arguments are passed as C strings. | 56 | String arguments are passed as C strings. |
| 52 | Integers are passed as C integers. */ | 57 | Integers are passed as C integers. */ |
| 53 | 58 | ||
| 54 | EMACS_INT | 59 | size_t |
| 55 | doprnt (char *buffer, register int bufsize, const char *format, | 60 | doprnt (char *buffer, register size_t bufsize, const char *format, |
| 56 | const char *format_end, va_list ap) | 61 | const char *format_end, va_list ap) |
| 57 | { | 62 | { |
| 58 | const char *fmt = format; /* Pointer into format string */ | 63 | const char *fmt = format; /* Pointer into format string */ |
| @@ -62,15 +67,15 @@ doprnt (char *buffer, register int bufsize, const char *format, | |||
| 62 | char tembuf[DBL_MAX_10_EXP + 100]; | 67 | char tembuf[DBL_MAX_10_EXP + 100]; |
| 63 | 68 | ||
| 64 | /* Size of sprintf_buffer. */ | 69 | /* Size of sprintf_buffer. */ |
| 65 | unsigned size_allocated = sizeof (tembuf); | 70 | size_t size_allocated = sizeof (tembuf); |
| 66 | 71 | ||
| 67 | /* Buffer to use for sprintf. Either tembuf or same as BIG_BUFFER. */ | 72 | /* Buffer to use for sprintf. Either tembuf or same as BIG_BUFFER. */ |
| 68 | char *sprintf_buffer = tembuf; | 73 | char *sprintf_buffer = tembuf; |
| 69 | 74 | ||
| 70 | /* Buffer we have got with malloc. */ | 75 | /* Buffer we have got with malloc. */ |
| 71 | char *big_buffer = 0; | 76 | char *big_buffer = NULL; |
| 72 | 77 | ||
| 73 | register int tem; | 78 | register size_t tem; |
| 74 | char *string; | 79 | char *string; |
| 75 | char fixed_buffer[20]; /* Default buffer for small formatting. */ | 80 | char fixed_buffer[20]; /* Default buffer for small formatting. */ |
| 76 | char *fmtcpy; | 81 | char *fmtcpy; |
| @@ -92,8 +97,9 @@ doprnt (char *buffer, register int bufsize, const char *format, | |||
| 92 | { | 97 | { |
| 93 | if (*fmt == '%') /* Check for a '%' character */ | 98 | if (*fmt == '%') /* Check for a '%' character */ |
| 94 | { | 99 | { |
| 95 | unsigned size_bound = 0; | 100 | size_t size_bound = 0; |
| 96 | EMACS_INT width; /* Columns occupied by STRING. */ | 101 | EMACS_INT width; /* Columns occupied by STRING on display. */ |
| 102 | int long_flag = 0; | ||
| 97 | 103 | ||
| 98 | fmt++; | 104 | fmt++; |
| 99 | /* Copy this one %-spec into fmtcpy. */ | 105 | /* Copy this one %-spec into fmtcpy. */ |
| @@ -108,10 +114,11 @@ doprnt (char *buffer, register int bufsize, const char *format, | |||
| 108 | This might be a field width or a precision; e.g. | 114 | This might be a field width or a precision; e.g. |
| 109 | %1.1000f and %1000.1f both might need 1000+ bytes. | 115 | %1.1000f and %1000.1f both might need 1000+ bytes. |
| 110 | Parse the width or precision, checking for overflow. */ | 116 | Parse the width or precision, checking for overflow. */ |
| 111 | unsigned n = *fmt - '0'; | 117 | size_t n = *fmt - '0'; |
| 112 | while ('0' <= fmt[1] && fmt[1] <= '9') | 118 | while ('0' <= fmt[1] && fmt[1] <= '9') |
| 113 | { | 119 | { |
| 114 | if (n * 10 + fmt[1] - '0' < n) | 120 | if (n >= SIZE_MAX / 10 |
| 121 | || n * 10 > SIZE_MAX - (fmt[1] - '0')) | ||
| 115 | error ("Format width or precision too large"); | 122 | error ("Format width or precision too large"); |
| 116 | n = n * 10 + fmt[1] - '0'; | 123 | n = n * 10 + fmt[1] - '0'; |
| 117 | *string++ = *++fmt; | 124 | *string++ = *++fmt; |
| @@ -122,6 +129,13 @@ doprnt (char *buffer, register int bufsize, const char *format, | |||
| 122 | } | 129 | } |
| 123 | else if (*fmt == '-' || *fmt == ' ' || *fmt == '.' || *fmt == '+') | 130 | else if (*fmt == '-' || *fmt == ' ' || *fmt == '.' || *fmt == '+') |
| 124 | ; | 131 | ; |
| 132 | else if (*fmt == 'l') | ||
| 133 | { | ||
| 134 | long_flag = 1; | ||
| 135 | if (!strchr ("dox", fmt[1])) | ||
| 136 | /* %l as conversion specifier, not as modifier. */ | ||
| 137 | break; | ||
| 138 | } | ||
| 125 | else | 139 | else |
| 126 | break; | 140 | break; |
| 127 | fmt++; | 141 | fmt++; |
| @@ -130,7 +144,7 @@ doprnt (char *buffer, register int bufsize, const char *format, | |||
| 130 | 144 | ||
| 131 | /* Make the size bound large enough to handle floating point formats | 145 | /* Make the size bound large enough to handle floating point formats |
| 132 | with large numbers. */ | 146 | with large numbers. */ |
| 133 | if (size_bound + DBL_MAX_10_EXP + 50 < size_bound) | 147 | if (size_bound > SIZE_MAX - DBL_MAX_10_EXP - 50) |
| 134 | error ("Format width or precision too large"); | 148 | error ("Format width or precision too large"); |
| 135 | size_bound += DBL_MAX_10_EXP + 50; | 149 | size_bound += DBL_MAX_10_EXP + 50; |
| 136 | 150 | ||
| @@ -151,23 +165,47 @@ doprnt (char *buffer, register int bufsize, const char *format, | |||
| 151 | error ("Invalid format operation %%%c", fmt[-1]); | 165 | error ("Invalid format operation %%%c", fmt[-1]); |
| 152 | 166 | ||
| 153 | /* case 'b': */ | 167 | /* case 'b': */ |
| 168 | case 'l': | ||
| 154 | case 'd': | 169 | case 'd': |
| 170 | { | ||
| 171 | int i; | ||
| 172 | long l; | ||
| 173 | |||
| 174 | if (long_flag) | ||
| 175 | { | ||
| 176 | l = va_arg(ap, long); | ||
| 177 | sprintf (sprintf_buffer, fmtcpy, l); | ||
| 178 | } | ||
| 179 | else | ||
| 180 | { | ||
| 181 | i = va_arg(ap, int); | ||
| 182 | sprintf (sprintf_buffer, fmtcpy, i); | ||
| 183 | } | ||
| 184 | /* Now copy into final output, truncating as necessary. */ | ||
| 185 | string = sprintf_buffer; | ||
| 186 | goto doit; | ||
| 187 | } | ||
| 188 | |||
| 155 | case 'o': | 189 | case 'o': |
| 156 | case 'x': | 190 | case 'x': |
| 157 | if (sizeof (int) == sizeof (EMACS_INT)) | 191 | { |
| 158 | ; | 192 | unsigned u; |
| 159 | else if (sizeof (long) == sizeof (EMACS_INT)) | 193 | unsigned long ul; |
| 160 | /* Insert an `l' the right place. */ | 194 | |
| 161 | string[1] = string[0], | 195 | if (long_flag) |
| 162 | string[0] = string[-1], | 196 | { |
| 163 | string[-1] = 'l', | 197 | ul = va_arg(ap, unsigned long); |
| 164 | string++; | 198 | sprintf (sprintf_buffer, fmtcpy, ul); |
| 165 | else | 199 | } |
| 166 | abort (); | 200 | else |
| 167 | sprintf (sprintf_buffer, fmtcpy, va_arg(ap, char *)); | 201 | { |
| 168 | /* Now copy into final output, truncating as nec. */ | 202 | u = va_arg(ap, unsigned); |
| 169 | string = sprintf_buffer; | 203 | sprintf (sprintf_buffer, fmtcpy, u); |
| 170 | goto doit; | 204 | } |
| 205 | /* Now copy into final output, truncating as necessary. */ | ||
| 206 | string = sprintf_buffer; | ||
| 207 | goto doit; | ||
| 208 | } | ||
| 171 | 209 | ||
| 172 | case 'f': | 210 | case 'f': |
| 173 | case 'e': | 211 | case 'e': |
| @@ -175,7 +213,7 @@ doprnt (char *buffer, register int bufsize, const char *format, | |||
| 175 | { | 213 | { |
| 176 | double d = va_arg(ap, double); | 214 | double d = va_arg(ap, double); |
| 177 | sprintf (sprintf_buffer, fmtcpy, d); | 215 | sprintf (sprintf_buffer, fmtcpy, d); |
| 178 | /* Now copy into final output, truncating as nec. */ | 216 | /* Now copy into final output, truncating as necessary. */ |
| 179 | string = sprintf_buffer; | 217 | string = sprintf_buffer; |
| 180 | goto doit; | 218 | goto doit; |
| 181 | } | 219 | } |
| @@ -187,13 +225,18 @@ doprnt (char *buffer, register int bufsize, const char *format, | |||
| 187 | minlen = atoi (&fmtcpy[1]); | 225 | minlen = atoi (&fmtcpy[1]); |
| 188 | string = va_arg (ap, char *); | 226 | string = va_arg (ap, char *); |
| 189 | tem = strlen (string); | 227 | tem = strlen (string); |
| 228 | if (tem > MOST_POSITIVE_FIXNUM) | ||
| 229 | error ("String for %%s or %%S format is too long"); | ||
| 190 | width = strwidth (string, tem); | 230 | width = strwidth (string, tem); |
| 191 | goto doit1; | 231 | goto doit1; |
| 192 | 232 | ||
| 193 | /* Copy string into final output, truncating if no room. */ | 233 | /* Copy string into final output, truncating if no room. */ |
| 194 | doit: | 234 | doit: |
| 195 | /* Coming here means STRING contains ASCII only. */ | 235 | /* Coming here means STRING contains ASCII only. */ |
| 196 | width = tem = strlen (string); | 236 | tem = strlen (string); |
| 237 | if (tem > MOST_POSITIVE_FIXNUM) | ||
| 238 | error ("Format width or precision too large"); | ||
| 239 | width = tem; | ||
| 197 | doit1: | 240 | doit1: |
| 198 | /* We have already calculated: | 241 | /* We have already calculated: |
| 199 | TEM -- length of STRING, | 242 | TEM -- length of STRING, |
| @@ -236,13 +279,8 @@ doprnt (char *buffer, register int bufsize, const char *format, | |||
| 236 | 279 | ||
| 237 | case 'c': | 280 | case 'c': |
| 238 | { | 281 | { |
| 239 | /* Sometimes for %c we pass a char, which would widen | 282 | int chr = va_arg(ap, int); |
| 240 | to int. Sometimes we pass XFASTINT() or XINT() | 283 | tem = CHAR_STRING (chr, (unsigned char *) charbuf); |
| 241 | values, which would be EMACS_INT. Let's hope that | ||
| 242 | both are passed the same way, otherwise we'll need | ||
| 243 | to rewrite callers. */ | ||
| 244 | EMACS_INT chr = va_arg(ap, EMACS_INT); | ||
| 245 | tem = CHAR_STRING ((int) chr, (unsigned char *) charbuf); | ||
| 246 | string = charbuf; | 284 | string = charbuf; |
| 247 | string[tem] = 0; | 285 | string[tem] = 0; |
| 248 | width = strwidth (string, tem); | 286 | width = strwidth (string, tem); |
| @@ -274,6 +312,6 @@ doprnt (char *buffer, register int bufsize, const char *format, | |||
| 274 | /* If we had to malloc something, free it. */ | 312 | /* If we had to malloc something, free it. */ |
| 275 | xfree (big_buffer); | 313 | xfree (big_buffer); |
| 276 | 314 | ||
| 277 | *bufptr = 0; /* Make sure our string end with a '\0' */ | 315 | *bufptr = 0; /* Make sure our string ends with a '\0' */ |
| 278 | return bufptr - buffer; | 316 | return bufptr - buffer; |
| 279 | } | 317 | } |
diff --git a/src/eval.c b/src/eval.c index b843ca5b2ec..c3676720940 100644 --- a/src/eval.c +++ b/src/eval.c | |||
| @@ -1416,7 +1416,8 @@ internal_lisp_condition_case (volatile Lisp_Object var, Lisp_Object bodyform, | |||
| 1416 | || (CONSP (tem) | 1416 | || (CONSP (tem) |
| 1417 | && (SYMBOLP (XCAR (tem)) | 1417 | && (SYMBOLP (XCAR (tem)) |
| 1418 | || CONSP (XCAR (tem)))))) | 1418 | || CONSP (XCAR (tem)))))) |
| 1419 | error ("Invalid condition handler"); | 1419 | error ("Invalid condition handler: %s", |
| 1420 | SDATA (Fprin1_to_string (tem, Qt))); | ||
| 1420 | } | 1421 | } |
| 1421 | 1422 | ||
| 1422 | c.tag = Qnil; | 1423 | c.tag = Qnil; |
| @@ -1995,31 +1996,31 @@ verror (const char *m, va_list ap) | |||
| 1995 | size_t size = sizeof buf; | 1996 | size_t size = sizeof buf; |
| 1996 | size_t size_max = | 1997 | size_t size_max = |
| 1997 | min (MOST_POSITIVE_FIXNUM, min (INT_MAX, SIZE_MAX - 1)) + 1; | 1998 | min (MOST_POSITIVE_FIXNUM, min (INT_MAX, SIZE_MAX - 1)) + 1; |
| 1999 | size_t mlen = strlen (m); | ||
| 1998 | char *buffer = buf; | 2000 | char *buffer = buf; |
| 1999 | int used; | 2001 | size_t used; |
| 2000 | Lisp_Object string; | 2002 | Lisp_Object string; |
| 2001 | 2003 | ||
| 2002 | while (1) | 2004 | while (1) |
| 2003 | { | 2005 | { |
| 2004 | used = vsnprintf (buffer, size, m, ap); | 2006 | used = doprnt (buffer, size, m, m + mlen, ap); |
| 2005 | 2007 | ||
| 2006 | if (used < 0) | 2008 | /* Note: the -1 below is because `doprnt' returns the number of bytes |
| 2007 | { | 2009 | excluding the terminating null byte, and it always terminates with a |
| 2008 | /* Non-C99 vsnprintf, such as w32, returns -1 when SIZE is too small. | 2010 | null byte, even when producing a truncated message. */ |
| 2009 | Guess a larger USED to work around the incompatibility. */ | 2011 | if (used < size - 1) |
| 2010 | used = (size <= size_max / 2 ? 2 * size | ||
| 2011 | : size < size_max ? size_max - 1 | ||
| 2012 | : size_max); | ||
| 2013 | } | ||
| 2014 | else if (used < size) | ||
| 2015 | break; | 2012 | break; |
| 2016 | if (size_max <= used) | 2013 | if (size <= size_max / 2) |
| 2017 | memory_full (); | 2014 | size *= 2; |
| 2018 | size = used + 1; | 2015 | else if (size < size_max - 1) |
| 2016 | size = size_max - 1; | ||
| 2017 | else | ||
| 2018 | break; /* and leave the message truncated */ | ||
| 2019 | 2019 | ||
| 2020 | if (buffer != buf) | 2020 | if (buffer == buf) |
| 2021 | xfree (buffer); | 2021 | buffer = (char *) xmalloc (size); |
| 2022 | buffer = (char *) xmalloc (size); | 2022 | else |
| 2023 | buffer = (char *) xrealloc (buffer, size); | ||
| 2023 | } | 2024 | } |
| 2024 | 2025 | ||
| 2025 | string = make_string (buffer, used); | 2026 | string = make_string (buffer, used); |
diff --git a/src/font.c b/src/font.c index 7fe0815d80e..f4950d39189 100644 --- a/src/font.c +++ b/src/font.c | |||
| @@ -1795,14 +1795,16 @@ check_otf_features (otf_features) | |||
| 1795 | { | 1795 | { |
| 1796 | CHECK_SYMBOL (Fcar (val)); | 1796 | CHECK_SYMBOL (Fcar (val)); |
| 1797 | if (SBYTES (SYMBOL_NAME (XCAR (val))) > 4) | 1797 | if (SBYTES (SYMBOL_NAME (XCAR (val))) > 4) |
| 1798 | error ("Invalid OTF GSUB feature: %s", SYMBOL_NAME (XCAR (val))); | 1798 | error ("Invalid OTF GSUB feature: %s", |
| 1799 | SDATA (SYMBOL_NAME (XCAR (val)))); | ||
| 1799 | } | 1800 | } |
| 1800 | otf_features = XCDR (otf_features); | 1801 | otf_features = XCDR (otf_features); |
| 1801 | for (val = Fcar (otf_features); ! NILP (val); val = Fcdr (val)) | 1802 | for (val = Fcar (otf_features); ! NILP (val); val = Fcdr (val)) |
| 1802 | { | 1803 | { |
| 1803 | CHECK_SYMBOL (Fcar (val)); | 1804 | CHECK_SYMBOL (Fcar (val)); |
| 1804 | if (SBYTES (SYMBOL_NAME (XCAR (val))) > 4) | 1805 | if (SBYTES (SYMBOL_NAME (XCAR (val))) > 4) |
| 1805 | error ("Invalid OTF GPOS feature: %s", SYMBOL_NAME (XCAR (val))); | 1806 | error ("Invalid OTF GPOS feature: %s", |
| 1807 | SDATA (SYMBOL_NAME (XCAR (val)))); | ||
| 1806 | } | 1808 | } |
| 1807 | } | 1809 | } |
| 1808 | 1810 | ||
diff --git a/src/lisp.h b/src/lisp.h index 581835dd32b..07b2cb0b1ef 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -2760,6 +2760,9 @@ extern Lisp_Object internal_with_output_to_temp_buffer | |||
| 2760 | extern void float_to_string (char *, double); | 2760 | extern void float_to_string (char *, double); |
| 2761 | extern void syms_of_print (void); | 2761 | extern void syms_of_print (void); |
| 2762 | 2762 | ||
| 2763 | /* Defined in doprnt.c */ | ||
| 2764 | extern size_t doprnt (char *, size_t, const char *, const char *, va_list); | ||
| 2765 | |||
| 2763 | /* Defined in lread.c. */ | 2766 | /* Defined in lread.c. */ |
| 2764 | extern Lisp_Object Qvariable_documentation, Qstandard_input; | 2767 | extern Lisp_Object Qvariable_documentation, Qstandard_input; |
| 2765 | extern Lisp_Object Qbackquote, Qcomma, Qcomma_at, Qcomma_dot, Qfunction; | 2768 | extern Lisp_Object Qbackquote, Qcomma, Qcomma_at, Qcomma_dot, Qfunction; |
diff --git a/src/makefile.w32-in b/src/makefile.w32-in index 62c40ca1f94..9d2c3d8f83f 100644 --- a/src/makefile.w32-in +++ b/src/makefile.w32-in | |||
| @@ -469,6 +469,7 @@ $(BLD)/callint.$(O) : \ | |||
| 469 | $(EMACS_ROOT)/nt/inc/sys/time.h \ | 469 | $(EMACS_ROOT)/nt/inc/sys/time.h \ |
| 470 | $(LISP_H) \ | 470 | $(LISP_H) \ |
| 471 | $(SRC)/buffer.h \ | 471 | $(SRC)/buffer.h \ |
| 472 | $(SRC)/character.h \ | ||
| 472 | $(SRC)/coding.h \ | 473 | $(SRC)/coding.h \ |
| 473 | $(SRC)/commands.h \ | 474 | $(SRC)/commands.h \ |
| 474 | $(SRC)/composite.h \ | 475 | $(SRC)/composite.h \ |
diff --git a/src/xdisp.c b/src/xdisp.c index 19fef35fce8..91d1b6ea2e3 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -8373,22 +8373,10 @@ vmessage (const char *m, va_list ap) | |||
| 8373 | { | 8373 | { |
| 8374 | if (m) | 8374 | if (m) |
| 8375 | { | 8375 | { |
| 8376 | char *buf = FRAME_MESSAGE_BUF (f); | 8376 | size_t len; |
| 8377 | size_t bufsize = FRAME_MESSAGE_BUF_SIZE (f); | ||
| 8378 | int len; | ||
| 8379 | 8377 | ||
| 8380 | memset (buf, 0, bufsize); | 8378 | len = doprnt (FRAME_MESSAGE_BUF (f), |
| 8381 | len = vsnprintf (buf, bufsize, m, ap); | 8379 | FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, ap); |
| 8382 | |||
| 8383 | /* Do any truncation at a character boundary. */ | ||
| 8384 | if (! (0 <= len && len < bufsize)) | ||
| 8385 | { | ||
| 8386 | char *end = memchr (buf, 0, bufsize); | ||
| 8387 | for (len = end ? end - buf : bufsize; | ||
| 8388 | len && ! CHAR_HEAD_P (buf[len - 1]); | ||
| 8389 | len--) | ||
| 8390 | continue; | ||
| 8391 | } | ||
| 8392 | 8380 | ||
| 8393 | message2 (FRAME_MESSAGE_BUF (f), len, 0); | 8381 | message2 (FRAME_MESSAGE_BUF (f), len, 0); |
| 8394 | } | 8382 | } |