From e6c3da2065ac72cc4e1a2bef22d367cd75401892 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 23 Apr 2011 13:33:28 +0300 Subject: Fix doprnt so it could be used safely in `verror'. (Bug#8435) src/doprnt.c: Include limits.h. (SIZE_MAX): New macro. (doprnt): Return a size_t value. 2nd arg is now size_t. Many local variables are now size_t instead of int or unsigned. Improve overflow protection. Support `l' modifier for integer conversions. Support %l conversion. Don't assume an EMACS_INT argument for integer conversions and for %c. src/lisp.h (doprnt): Restore prototype. src/makefile.w32-in ($(BLD)/callint.$(O)): Depend on $(SRC)/character.h. src/Makefile.in (base_obj): Add back doprnt.o. src/deps.mk (doprnt.o): Add back prerequisites. (callint.o): Depend on character.h. src/eval.c (internal_lisp_condition_case): Include the handler representation in the error message. (verror): Call doprnt instead of vsnprintf. Fix an off-by-one bug when breaking from the loop. src/xdisp.c (vmessage): Call doprnt instead of vsnprintf. src/callint.c (Fcall_interactively): When displaying error message about invalid control letter, pass the character's codepoint, not a pointer to its multibyte form. Improve display of the character in octal and display also its hex code. src/character.c (char_string): Use %x to display the (unsigned) codepoint of an invalid character, to avoid displaying a bogus negative value. src/font.c (check_otf_features): Pass SDATA of SYMBOL_NAME to `error', not SYMBOL_NAME itself. src/coding.c (Fencode_sjis_char, Fencode_big5_char): Use %c for character arguments to `error'. src/charset.c (check_iso_charset_parameter): Fix incorrect argument to `error' in error message about FINAL_CHAR argument. Make sure FINAL_CHAR is a character, and use %c when it is passed as argument to `error'. --- src/eval.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) (limited to 'src/eval.c') 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, || (CONSP (tem) && (SYMBOLP (XCAR (tem)) || CONSP (XCAR (tem)))))) - error ("Invalid condition handler"); + error ("Invalid condition handler: %s", + SDATA (Fprin1_to_string (tem, Qt))); } c.tag = Qnil; @@ -1995,31 +1996,31 @@ verror (const char *m, va_list ap) size_t size = sizeof buf; size_t size_max = min (MOST_POSITIVE_FIXNUM, min (INT_MAX, SIZE_MAX - 1)) + 1; + size_t mlen = strlen (m); char *buffer = buf; - int used; + size_t used; Lisp_Object string; while (1) { - used = vsnprintf (buffer, size, m, ap); + used = doprnt (buffer, size, m, m + mlen, ap); - if (used < 0) - { - /* Non-C99 vsnprintf, such as w32, returns -1 when SIZE is too small. - Guess a larger USED to work around the incompatibility. */ - used = (size <= size_max / 2 ? 2 * size - : size < size_max ? size_max - 1 - : size_max); - } - else if (used < size) + /* Note: the -1 below is because `doprnt' returns the number of bytes + excluding the terminating null byte, and it always terminates with a + null byte, even when producing a truncated message. */ + if (used < size - 1) break; - if (size_max <= used) - memory_full (); - size = used + 1; + if (size <= size_max / 2) + size *= 2; + else if (size < size_max - 1) + size = size_max - 1; + else + break; /* and leave the message truncated */ - if (buffer != buf) - xfree (buffer); - buffer = (char *) xmalloc (size); + if (buffer == buf) + buffer = (char *) xmalloc (size); + else + buffer = (char *) xrealloc (buffer, size); } string = make_string (buffer, used); -- cgit v1.2.1