aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/ChangeLog11
-rw-r--r--src/doprnt.c18
-rw-r--r--src/eval.c10
-rw-r--r--src/lisp.h3
-rw-r--r--src/xdisp.c2
5 files changed, 28 insertions, 16 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index d91837877e..6e63fdd633 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,16 @@
2011-07-07 Paul Eggert <[email protected]>
+ * 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 0632046525..79f9f36e46 100644
--- a/src/doprnt.c
+++ b/src/doprnt.c
@@ -129,8 +129,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
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 90d0df6185..ef169e80e2 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 cd3cfd316a..f16a32e633 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 a99f06a4e4..c1347e2dc2 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);