Commit 94dcfacf authored by Eli Zaretskii's avatar Eli Zaretskii

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.
parent 211ec907
2011-04-27 Eli Zaretskii <eliz@gnu.org>
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 <kasahara@nc.kyushu-u.ac.jp> (tiny change) 2011-04-27 Yoshiaki Kasahara <kasahara@nc.kyushu-u.ac.jp> (tiny change)
* buffer.c (init_buffer) [USE_MMAP_FOR_BUFFERS]: Adjust to aliasing * buffer.c (init_buffer) [USE_MMAP_FOR_BUFFERS]: Adjust to aliasing
......
...@@ -9282,14 +9282,15 @@ usage: (find-operation-coding-system OPERATION ARGUMENTS...) */) ...@@ -9282,14 +9282,15 @@ usage: (find-operation-coding-system OPERATION ARGUMENTS...) */)
|| !NATNUMP (target_idx = Fget (operation, Qtarget_idx))) || !NATNUMP (target_idx = Fget (operation, Qtarget_idx)))
error ("Invalid first argument"); error ("Invalid first argument");
if (nargs < 1 + XFASTINT (target_idx)) if (nargs < 1 + XFASTINT (target_idx))
error ("Too few arguments for operation: %s", error ("Too few arguments for operation `%s'",
SDATA (SYMBOL_NAME (operation))); SDATA (SYMBOL_NAME (operation)));
target = args[XFASTINT (target_idx) + 1]; target = args[XFASTINT (target_idx) + 1];
if (!(STRINGP (target) if (!(STRINGP (target)
|| (EQ (operation, Qinsert_file_contents) && CONSP (target) || (EQ (operation, Qinsert_file_contents) && CONSP (target)
&& STRINGP (XCAR (target)) && BUFFERP (XCDR (target))) && STRINGP (XCAR (target)) && BUFFERP (XCDR (target)))
|| (EQ (operation, Qopen_network_stream) && INTEGERP (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)) if (CONSP (target))
target = XCAR (target); target = XCAR (target);
......
...@@ -55,7 +55,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ ...@@ -55,7 +55,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
%s means print a string argument. %s means print a string argument.
%S is silently treated as %s, for loose compatibility with `Fformat'. %S is silently treated as %s, for loose compatibility with `Fformat'.
%d means print a `signed int' argument in decimal. %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. %o means print an `unsigned int' argument in octal.
%x means print an `unsigned int' argument in hex. %x means print an `unsigned int' argument in hex.
%e means print a `double' argument in exponential notation. %e means print a `double' argument in exponential notation.
...@@ -65,22 +64,26 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ ...@@ -65,22 +64,26 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
%c means print a `signed int' argument as a single character. %c means print a `signed int' argument as a single character.
%% means produce a literal % character. %% means produce a literal % character.
A %-sequence may contain optional flag, width, and precision specifiers, as A %-sequence may contain optional flag, width, and precision specifiers, and
follows: a length modifier, as follows:
%<flags><width><precision>character %<flags><width><precision><length>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 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, inserts a space before any positive number; these flags only affect %d, %o,
%o, %x, %e, %f, and %g sequences. The - and 0 flags affect the width %x, %e, %f, and %g sequences. The - and 0 flags affect the width specifier,
specifier, as described below. 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
The l (lower-case letter ell) flag is a `long' data type modifier: it is start with a sign (+ or -).
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 The l (lower-case letter ell) length modifier is a `long' data type
long int'. The EMACS_INT data type should use this modifier. 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 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 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, ...@@ -166,7 +169,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format,
bufsize--; bufsize--;
/* Loop until end of format string or buffer full. */ /* 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 */ if (*fmt == '%') /* Check for a '%' character */
{ {
...@@ -178,7 +181,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format, ...@@ -178,7 +181,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format,
/* Copy this one %-spec into fmtcpy. */ /* Copy this one %-spec into fmtcpy. */
string = fmtcpy; string = fmtcpy;
*string++ = '%'; *string++ = '%';
while (1) while (fmt < format_end)
{ {
*string++ = *fmt; *string++ = *fmt;
if ('0' <= *fmt && *fmt <= '9') if ('0' <= *fmt && *fmt <= '9')
...@@ -188,7 +191,8 @@ doprnt (char *buffer, register size_t bufsize, const char *format, ...@@ -188,7 +191,8 @@ doprnt (char *buffer, register size_t bufsize, const char *format,
%1.1000f and %1000.1f both might need 1000+ bytes. %1.1000f and %1000.1f both might need 1000+ bytes.
Parse the width or precision, checking for overflow. */ Parse the width or precision, checking for overflow. */
size_t n = *fmt - '0'; 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 if (n >= SIZE_MAX / 10
|| n * 10 > SIZE_MAX - (fmt[1] - '0')) || n * 10 > SIZE_MAX - (fmt[1] - '0'))
...@@ -205,14 +209,15 @@ doprnt (char *buffer, register size_t bufsize, const char *format, ...@@ -205,14 +209,15 @@ doprnt (char *buffer, register size_t bufsize, const char *format,
else if (*fmt == 'l') else if (*fmt == 'l')
{ {
long_flag = 1; long_flag = 1;
if (!strchr ("dox", fmt[1])) fmt++;
/* %l as conversion specifier, not as modifier. */ break;
break;
} }
else else
break; break;
fmt++; fmt++;
} }
if (fmt > format_end)
fmt = format_end;
*string = 0; *string = 0;
/* Make the size bound large enough to handle floating point formats /* 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, ...@@ -225,9 +230,8 @@ doprnt (char *buffer, register size_t bufsize, const char *format,
if (size_bound > size_allocated) if (size_bound > size_allocated)
{ {
if (big_buffer) if (big_buffer)
big_buffer = (char *) xrealloc (big_buffer, size_bound); xfree (big_buffer);
else big_buffer = (char *) xmalloc (size_bound);
big_buffer = (char *) xmalloc (size_bound);
sprintf_buffer = big_buffer; sprintf_buffer = big_buffer;
size_allocated = size_bound; size_allocated = size_bound;
} }
...@@ -235,7 +239,8 @@ doprnt (char *buffer, register size_t bufsize, const char *format, ...@@ -235,7 +239,8 @@ doprnt (char *buffer, register size_t bufsize, const char *format,
switch (*fmt++) switch (*fmt++)
{ {
default: default:
error ("Invalid format operation %%%c", fmt[-1]); error ("Invalid format operation %%%s%c",
long_flag ? "l" : "", fmt[-1]);
/* case 'b': */ /* case 'b': */
case 'l': case 'l':
...@@ -373,7 +378,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format, ...@@ -373,7 +378,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format,
char *save_bufptr = bufptr; char *save_bufptr = bufptr;
do { *bufptr++ = *fmt++; } 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)) if (!CHAR_HEAD_P (*fmt))
{ {
bufptr = save_bufptr; bufptr = save_bufptr;
......
...@@ -1994,8 +1994,7 @@ verror (const char *m, va_list ap) ...@@ -1994,8 +1994,7 @@ verror (const char *m, va_list ap)
{ {
char buf[4000]; char buf[4000];
size_t size = sizeof buf; size_t size = sizeof buf;
size_t size_max = size_t size_max = min (MOST_POSITIVE_FIXNUM, SIZE_MAX);
min (MOST_POSITIVE_FIXNUM, min (INT_MAX, SIZE_MAX - 1)) + 1;
size_t mlen = strlen (m); size_t mlen = strlen (m);
char *buffer = buf; char *buffer = buf;
size_t used; size_t used;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment