From c2d1e36da89642b8916965a967b000aff7d59099 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 6 Jul 2011 19:14:52 -0700 Subject: [PATCH] * 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. --- src/ChangeLog | 11 +++++++++++ src/doprnt.c | 18 +++++++++--------- src/eval.c | 10 +++++----- src/lisp.h | 3 ++- src/xdisp.c | 2 +- 5 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index d91837877e1..6e63fdd6333 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,16 @@ 2011-07-07 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. + Assume freestanding C89 headers, string.h, stdlib.h. * data.c, doprnt.c, floatfns.c, print.c: Include float.h unconditionally. diff --git a/src/doprnt.c b/src/doprnt.c index 0632046525a..79f9f36e461 100644 --- a/src/doprnt.c +++ b/src/doprnt.c @@ -129,8 +129,8 @@ along with GNU Emacs. If not, see . */ String arguments are passed as C strings. Integers are passed as C integers. */ -size_t -doprnt (char *buffer, register size_t bufsize, const char *format, +ptrdiff_t +doprnt (char *buffer, ptrdiff_t bufsize, const char *format, const char *format_end, va_list ap) { const char *fmt = format; /* Pointer into format string */ @@ -140,7 +140,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format, char tembuf[DBL_MAX_10_EXP + 100]; /* 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. */ char *sprintf_buffer = tembuf; @@ -159,7 +159,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format, if (format_end == 0) format_end = format + strlen (format); - if ((format_end - format + 1) < sizeof (fixed_buffer)) + if (format_end - format < sizeof (fixed_buffer) - 1) fmtcpy = fixed_buffer; else SAFE_ALLOCA (fmtcpy, char *, format_end - format + 1); @@ -171,7 +171,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format, { 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. */ int long_flag = 0; int pIlen = sizeof pI - 1; @@ -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. %1.1000f and %1000.1f both might need 1000+ bytes. Parse the width or precision, checking for overflow. */ - size_t n = *fmt - '0'; + ptrdiff_t n = *fmt - '0'; while (fmt + 1 < format_end && '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. This test is simple but slightly conservative: e.g., (INT_MAX - INT_MAX % 10) is reported as an overflow 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"); n = n * 10 + fmt[1] - '0'; *string++ = *++fmt; @@ -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 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"); size_bound += DBL_MAX_10_EXP + 50; diff --git a/src/eval.c b/src/eval.c index 90d0df61858..ef169e80e27 100644 --- a/src/eval.c +++ b/src/eval.c @@ -1968,18 +1968,18 @@ void verror (const char *m, va_list ap) { char buf[4000]; - size_t size = sizeof buf; - size_t size_max = STRING_BYTES_BOUND + 1; - size_t mlen = strlen (m); + ptrdiff_t size = sizeof buf; + ptrdiff_t size_max = STRING_BYTES_BOUND + 1; + char const *m_end = m + strlen (m); char *buffer = buf; - size_t used; + ptrdiff_t used; Lisp_Object string; while (1) { va_list ap_copy; 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); /* Note: the -1 below is because `doprnt' returns the number of bytes diff --git a/src/lisp.h b/src/lisp.h index cd3cfd316a5..f16a32e6331 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -2868,7 +2868,8 @@ extern void float_to_string (char *, double); extern void syms_of_print (void); /* 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. */ extern Lisp_Object Qvariable_documentation, Qstandard_input; diff --git a/src/xdisp.c b/src/xdisp.c index a99f06a4e45..c1347e2dc27 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -8485,7 +8485,7 @@ vmessage (const char *m, va_list ap) { if (m) { - size_t len; + ptrdiff_t len; len = doprnt (FRAME_MESSAGE_BUF (f), FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, ap); -- 2.39.2