Commit c2d1e36d authored by Paul Eggert's avatar Paul Eggert

* doprnt.c: Prefer signed to unsigned when either works.

* eval.c (verror):
* doprnt.c (doprnt):
* lisp.h (doprnt):
* xdisp.c (vmessage):
Use ptrdiff_t, not size_t, when using or implementing doprnt,
since the sizes cannot exceed ptrdiff_t bounds anyway, and we
prefer signed arithmetic to avoid comparison confusion.
* doprnt.c (doprnt): Avoid a "+ 1" that can't overflow,
but is a bit tricky.
parent 0e926e56
2011-07-07 Paul Eggert <eggert@cs.ucla.edu> 2011-07-07 Paul Eggert <eggert@cs.ucla.edu>
* doprnt.c: Prefer signed to unsigned when either works.
* eval.c (verror):
* doprnt.c (doprnt):
* lisp.h (doprnt):
* xdisp.c (vmessage):
Use ptrdiff_t, not size_t, when using or implementing doprnt,
since the sizes cannot exceed ptrdiff_t bounds anyway, and we
prefer signed arithmetic to avoid comparison confusion.
* doprnt.c (doprnt): Avoid a "+ 1" that can't overflow,
but is a bit tricky.
Assume freestanding C89 headers, string.h, stdlib.h. Assume freestanding C89 headers, string.h, stdlib.h.
* data.c, doprnt.c, floatfns.c, print.c: * data.c, doprnt.c, floatfns.c, print.c:
Include float.h unconditionally. Include float.h unconditionally.
......
...@@ -129,8 +129,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ ...@@ -129,8 +129,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
String arguments are passed as C strings. String arguments are passed as C strings.
Integers are passed as C integers. */ Integers are passed as C integers. */
size_t ptrdiff_t
doprnt (char *buffer, register size_t bufsize, const char *format, doprnt (char *buffer, ptrdiff_t bufsize, const char *format,
const char *format_end, va_list ap) const char *format_end, va_list ap)
{ {
const char *fmt = format; /* Pointer into format string */ const char *fmt = format; /* Pointer into format string */
...@@ -140,7 +140,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format, ...@@ -140,7 +140,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format,
char tembuf[DBL_MAX_10_EXP + 100]; char tembuf[DBL_MAX_10_EXP + 100];
/* Size of sprintf_buffer. */ /* Size of sprintf_buffer. */
size_t size_allocated = sizeof (tembuf); ptrdiff_t size_allocated = sizeof (tembuf);
/* Buffer to use for sprintf. Either tembuf or same as BIG_BUFFER. */ /* Buffer to use for sprintf. Either tembuf or same as BIG_BUFFER. */
char *sprintf_buffer = tembuf; char *sprintf_buffer = tembuf;
...@@ -159,7 +159,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format, ...@@ -159,7 +159,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format,
if (format_end == 0) if (format_end == 0)
format_end = format + strlen (format); format_end = format + strlen (format);
if ((format_end - format + 1) < sizeof (fixed_buffer)) if (format_end - format < sizeof (fixed_buffer) - 1)
fmtcpy = fixed_buffer; fmtcpy = fixed_buffer;
else else
SAFE_ALLOCA (fmtcpy, char *, format_end - format + 1); SAFE_ALLOCA (fmtcpy, char *, format_end - format + 1);
...@@ -171,7 +171,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format, ...@@ -171,7 +171,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format,
{ {
if (*fmt == '%') /* Check for a '%' character */ if (*fmt == '%') /* Check for a '%' character */
{ {
size_t size_bound = 0; ptrdiff_t size_bound = 0;
EMACS_INT width; /* Columns occupied by STRING on display. */ EMACS_INT width; /* Columns occupied by STRING on display. */
int long_flag = 0; int long_flag = 0;
int pIlen = sizeof pI - 1; int pIlen = sizeof pI - 1;
...@@ -189,16 +189,16 @@ doprnt (char *buffer, register size_t bufsize, const char *format, ...@@ -189,16 +189,16 @@ doprnt (char *buffer, register size_t bufsize, const char *format,
This might be a field width or a precision; e.g. This might be a field width or a precision; e.g.
%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'; ptrdiff_t n = *fmt - '0';
while (fmt + 1 < format_end while (fmt + 1 < format_end
&& '0' <= fmt[1] && fmt[1] <= '9') && '0' <= fmt[1] && fmt[1] <= '9')
{ {
/* Avoid size_t overflow. Avoid int overflow too, as /* Avoid ptrdiff_t, size_t, and int overflow, as
many sprintfs mishandle widths greater than INT_MAX. many sprintfs mishandle widths greater than INT_MAX.
This test is simple but slightly conservative: e.g., This test is simple but slightly conservative: e.g.,
(INT_MAX - INT_MAX % 10) is reported as an overflow (INT_MAX - INT_MAX % 10) is reported as an overflow
even when it's not. */ even when it's not. */
if (n >= min (INT_MAX, SIZE_MAX) / 10) if (n >= min (INT_MAX, min (PTRDIFF_MAX, SIZE_MAX)) / 10)
error ("Format width or precision too large"); error ("Format width or precision too large");
n = n * 10 + fmt[1] - '0'; n = n * 10 + fmt[1] - '0';
*string++ = *++fmt; *string++ = *++fmt;
...@@ -230,7 +230,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format, ...@@ -230,7 +230,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format,
/* Make the size bound large enough to handle floating point formats /* Make the size bound large enough to handle floating point formats
with large numbers. */ with large numbers. */
if (size_bound > SIZE_MAX - DBL_MAX_10_EXP - 50) if (size_bound > min (PTRDIFF_MAX, SIZE_MAX) - DBL_MAX_10_EXP - 50)
error ("Format width or precision too large"); error ("Format width or precision too large");
size_bound += DBL_MAX_10_EXP + 50; size_bound += DBL_MAX_10_EXP + 50;
......
...@@ -1968,18 +1968,18 @@ void ...@@ -1968,18 +1968,18 @@ void
verror (const char *m, va_list ap) verror (const char *m, va_list ap)
{ {
char buf[4000]; char buf[4000];
size_t size = sizeof buf; ptrdiff_t size = sizeof buf;
size_t size_max = STRING_BYTES_BOUND + 1; ptrdiff_t size_max = STRING_BYTES_BOUND + 1;
size_t mlen = strlen (m); char const *m_end = m + strlen (m);
char *buffer = buf; char *buffer = buf;
size_t used; ptrdiff_t used;
Lisp_Object string; Lisp_Object string;
while (1) while (1)
{ {
va_list ap_copy; va_list ap_copy;
va_copy (ap_copy, ap); va_copy (ap_copy, ap);
used = doprnt (buffer, size, m, m + mlen, ap_copy); used = doprnt (buffer, size, m, m_end, ap_copy);
va_end (ap_copy); va_end (ap_copy);
/* Note: the -1 below is because `doprnt' returns the number of bytes /* Note: the -1 below is because `doprnt' returns the number of bytes
......
...@@ -2868,7 +2868,8 @@ extern void float_to_string (char *, double); ...@@ -2868,7 +2868,8 @@ extern void float_to_string (char *, double);
extern void syms_of_print (void); extern void syms_of_print (void);
/* Defined in doprnt.c */ /* Defined in doprnt.c */
extern size_t doprnt (char *, size_t, const char *, const char *, va_list); extern ptrdiff_t doprnt (char *, ptrdiff_t, const char *, const char *,
va_list);
/* Defined in lread.c. */ /* Defined in lread.c. */
extern Lisp_Object Qvariable_documentation, Qstandard_input; extern Lisp_Object Qvariable_documentation, Qstandard_input;
......
...@@ -8485,7 +8485,7 @@ vmessage (const char *m, va_list ap) ...@@ -8485,7 +8485,7 @@ vmessage (const char *m, va_list ap)
{ {
if (m) if (m)
{ {
size_t len; ptrdiff_t len;
len = doprnt (FRAME_MESSAGE_BUF (f), len = doprnt (FRAME_MESSAGE_BUF (f),
FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, ap); FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, ap);
......
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