From 94dcfacf129aa99be3e375187d75a193ffe26bad Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Wed, 27 Apr 2011 21:15:29 +0300 Subject: [PATCH] Improve `doprnt' and its usage. (Bug#8545) src/doprnt.c (doprnt): Make sure `format' is never accessed beyond `format_end'. Remove support for %l as a conversion specifier. Don't use xrealloc. Improve diagnostics when the %l size modifier is used. Update the commentary. src/eval.c (verror): Simplify calculation of size_t. src/coding.c (Ffind_operation_coding_system): Fix diagnostic error messages. --- src/ChangeLog | 13 +++++++++++++ src/coding.c | 5 +++-- src/doprnt.c | 53 ++++++++++++++++++++++++++++----------------------- src/eval.c | 3 +-- 4 files changed, 46 insertions(+), 28 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index e2ac23256a..c08ef73ca1 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,16 @@ +2011-04-27 Eli Zaretskii + + Improve `doprnt' and its usage. (Bug#8545) + * doprnt.c (doprnt): Make sure `format' is never accessed beyond + `format_end'. Remove support for %l as a conversion specifier. + Don't use xrealloc. Improve diagnostics when the %l size modifier + is used. Update the commentary. + + * eval.c (verror): Simplify calculation of size_t. + + * coding.c (Ffind_operation_coding_system): Fix diagnostic error + messages. + 2011-04-27 Yoshiaki Kasahara (tiny change) * buffer.c (init_buffer) [USE_MMAP_FOR_BUFFERS]: Adjust to aliasing diff --git a/src/coding.c b/src/coding.c index c14a41036a..c129c94203 100644 --- a/src/coding.c +++ b/src/coding.c @@ -9282,14 +9282,15 @@ usage: (find-operation-coding-system OPERATION ARGUMENTS...) */) || !NATNUMP (target_idx = Fget (operation, Qtarget_idx))) error ("Invalid first argument"); if (nargs < 1 + XFASTINT (target_idx)) - error ("Too few arguments for operation: %s", + error ("Too few arguments for operation `%s'", SDATA (SYMBOL_NAME (operation))); target = args[XFASTINT (target_idx) + 1]; if (!(STRINGP (target) || (EQ (operation, Qinsert_file_contents) && CONSP (target) && STRINGP (XCAR (target)) && BUFFERP (XCDR (target))) || (EQ (operation, Qopen_network_stream) && INTEGERP (target)))) - error ("Invalid %"pI"dth argument", XFASTINT (target_idx) + 1); + error ("Invalid argument %"pI"d of operation `%s'", + XFASTINT (target_idx) + 1, SDATA (SYMBOL_NAME (operation))); if (CONSP (target)) target = XCAR (target); diff --git a/src/doprnt.c b/src/doprnt.c index 3ac1d9963a..92e2d62743 100644 --- a/src/doprnt.c +++ b/src/doprnt.c @@ -55,7 +55,6 @@ along with GNU Emacs. If not, see . */ %s means print a string argument. %S is silently treated as %s, for loose compatibility with `Fformat'. %d means print a `signed int' argument in decimal. - %l means print a `long int' argument in decimal. %o means print an `unsigned int' argument in octal. %x means print an `unsigned int' argument in hex. %e means print a `double' argument in exponential notation. @@ -65,22 +64,26 @@ along with GNU Emacs. If not, see . */ %c means print a `signed int' argument as a single character. %% means produce a literal % character. - A %-sequence may contain optional flag, width, and precision specifiers, as - follows: + A %-sequence may contain optional flag, width, and precision specifiers, and + a length modifier, as follows: - %character + %character - where flags is [+ -0l], width is [0-9]+, and precision is .[0-9]+ + where flags is [+ -0], width is [0-9]+, precision is .[0-9]+, and length + modifier is l. The + flag character inserts a + before any positive number, while a space - inserts a space before any positive number; these flags only affect %d, %l, - %o, %x, %e, %f, and %g sequences. The - and 0 flags affect the width - specifier, as described below. - - The l (lower-case letter ell) flag is a `long' data type modifier: it is - supported for %d, %o, and %x conversions of integral arguments, and means - that the respective argument is to be treated as `long int' or `unsigned - long int'. The EMACS_INT data type should use this modifier. + inserts a space before any positive number; these flags only affect %d, %o, + %x, %e, %f, and %g sequences. The - and 0 flags affect the width specifier, + as described below. For signed numerical arguments only, the ` ' (space) + flag causes the result to be prefixed with a space character if it does not + start with a sign (+ or -). + + The l (lower-case letter ell) length modifier is a `long' data type + modifier: it is supported for %d, %o, and %x conversions of integral + arguments, must immediately preced the conversion specifier, and means that + the respective argument is to be treated as `long int' or `unsigned long + int'. The EMACS_INT data type should use this modifier. The width specifier supplies a lower limit for the length of the printed representation. The padding, if any, normally goes on the left, but it goes @@ -166,7 +169,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format, bufsize--; /* Loop until end of format string or buffer full. */ - while (fmt != format_end && bufsize > 0) + while (fmt < format_end && bufsize > 0) { if (*fmt == '%') /* Check for a '%' character */ { @@ -178,7 +181,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format, /* Copy this one %-spec into fmtcpy. */ string = fmtcpy; *string++ = '%'; - while (1) + while (fmt < format_end) { *string++ = *fmt; if ('0' <= *fmt && *fmt <= '9') @@ -188,7 +191,8 @@ doprnt (char *buffer, register size_t bufsize, const char *format, %1.1000f and %1000.1f both might need 1000+ bytes. Parse the width or precision, checking for overflow. */ size_t n = *fmt - '0'; - while ('0' <= fmt[1] && fmt[1] <= '9') + while (fmt < format_end + && '0' <= fmt[1] && fmt[1] <= '9') { if (n >= SIZE_MAX / 10 || n * 10 > SIZE_MAX - (fmt[1] - '0')) @@ -205,14 +209,15 @@ doprnt (char *buffer, register size_t bufsize, const char *format, else if (*fmt == 'l') { long_flag = 1; - if (!strchr ("dox", fmt[1])) - /* %l as conversion specifier, not as modifier. */ - break; + fmt++; + break; } else break; fmt++; } + if (fmt > format_end) + fmt = format_end; *string = 0; /* Make the size bound large enough to handle floating point formats @@ -225,9 +230,8 @@ doprnt (char *buffer, register size_t bufsize, const char *format, if (size_bound > size_allocated) { if (big_buffer) - big_buffer = (char *) xrealloc (big_buffer, size_bound); - else - big_buffer = (char *) xmalloc (size_bound); + xfree (big_buffer); + big_buffer = (char *) xmalloc (size_bound); sprintf_buffer = big_buffer; size_allocated = size_bound; } @@ -235,7 +239,8 @@ doprnt (char *buffer, register size_t bufsize, const char *format, switch (*fmt++) { default: - error ("Invalid format operation %%%c", fmt[-1]); + error ("Invalid format operation %%%s%c", + long_flag ? "l" : "", fmt[-1]); /* case 'b': */ case 'l': @@ -373,7 +378,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format, char *save_bufptr = bufptr; do { *bufptr++ = *fmt++; } - while (--bufsize > 0 && !CHAR_HEAD_P (*fmt)); + while (fmt < format_end && --bufsize > 0 && !CHAR_HEAD_P (*fmt)); if (!CHAR_HEAD_P (*fmt)) { bufptr = save_bufptr; diff --git a/src/eval.c b/src/eval.c index 8716ad7846..bcbbf74015 100644 --- a/src/eval.c +++ b/src/eval.c @@ -1994,8 +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, min (INT_MAX, SIZE_MAX - 1)) + 1; + size_t size_max = min (MOST_POSITIVE_FIXNUM, SIZE_MAX); size_t mlen = strlen (m); char *buffer = buf; size_t used; -- 2.20.1