* src/charset.c (read_hex): Use INT_LEFT_SHIFT_OVERFLOW for clarity.
The machine code is the same on my platform.
* src/doprnt.c (doprnt):
* src/emacs-module.c (module_funcall):
* src/font.c (font_intern_prop):
* src/keyboard.c (Frecursion_depth):
* src/lread.c (read1):
Use WRAPV macros instead of checking overflow by hand.
* src/editfns.c (hi_time, time_arith, decode_time_components):
* src/emacs-module.c (Fmodule_load):
Simplify by using FIXNUM_OVERFLOW_P.
* src/emacs-module.c: Include intprops.h.
* src/xdisp.c (percent99): New function.
(decode_mode_spec): Use it to simplify overflow avoidance and
formatting of %p and %P.
n = 0;
while (c_isxdigit (c = getc (fp)))
{
- if (UINT_MAX >> 4 < n)
+ if (INT_LEFT_SHIFT_OVERFLOW (n, 4))
*overflow = 1;
n = ((n << 4)
| (c - ('0' <= c && c <= '9' ? '0'
const char *fmt = format; /* Pointer into format string. */
char *bufptr = buffer; /* Pointer into output buffer. */
+ /* Enough to handle floating point formats with large numbers. */
+ enum { SIZE_BOUND_EXTRA = DBL_MAX_10_EXP + 50 };
+
/* Use this for sprintf unless we need something really big. */
- char tembuf[DBL_MAX_10_EXP + 100];
+ char tembuf[SIZE_BOUND_EXTRA + 50];
/* Size of sprintf_buffer. */
ptrdiff_t size_allocated = sizeof (tembuf);
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. */
- ptrdiff_t n = *fmt - '0';
+ int n = *fmt - '0';
+ bool overflow = false;
while (fmt + 1 < format_end
&& '0' <= fmt[1] && fmt[1] <= '9')
{
- /* 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, min (PTRDIFF_MAX, SIZE_MAX)) / 10)
- error ("Format width or precision too large");
- n = n * 10 + fmt[1] - '0';
+ overflow |= INT_MULTIPLY_WRAPV (n, 10, &n);
+ overflow |= INT_ADD_WRAPV (n, fmt[1] - '0', &n);
*string++ = *++fmt;
}
+ if (overflow
+ || min (PTRDIFF_MAX, SIZE_MAX) - SIZE_BOUND_EXTRA < n)
+ error ("Format width or precision too large");
if (size_bound < n)
size_bound = n;
}
/* Make the size bound large enough to handle floating point formats
with large numbers. */
- 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;
+ size_bound += SIZE_BOUND_EXTRA;
/* Make sure we have that much. */
if (size_bound > size_allocated)
hi_time (time_t t)
{
time_t hi = t >> LO_TIME_BITS;
-
- /* Check for overflow, helping the compiler for common cases where
- no runtime check is needed, and taking care not to convert
- negative numbers to unsigned before comparing them. */
- if (! ((! TYPE_SIGNED (time_t)
- || MOST_NEGATIVE_FIXNUM <= TIME_T_MIN >> LO_TIME_BITS
- || MOST_NEGATIVE_FIXNUM <= hi)
- && (TIME_T_MAX >> LO_TIME_BITS <= MOST_POSITIVE_FIXNUM
- || hi <= MOST_POSITIVE_FIXNUM)))
+ if (FIXNUM_OVERFLOW_P (hi))
time_overflow ();
-
return hi;
}
struct lisp_time ta = lisp_time_struct (a, &alen);
struct lisp_time tb = lisp_time_struct (b, &blen);
struct lisp_time t = op (ta, tb);
- if (! (MOST_NEGATIVE_FIXNUM <= t.hi && t.hi <= MOST_POSITIVE_FIXNUM))
+ if (FIXNUM_OVERFLOW_P (t.hi))
time_overflow ();
Lisp_Object val = Qnil;
if (result)
{
- if (! (MOST_NEGATIVE_FIXNUM <= hi && hi <= MOST_POSITIVE_FIXNUM))
+ if (FIXNUM_OVERFLOW_P (hi))
return -1;
result->hi = hi;
result->lo = lo;
#include "lisp.h"
#include "dynlib.h"
#include "coding.h"
-#include "verify.h"
+
+#include <intprops.h>
+#include <verify.h>
\f
/* Feature tests. */
first arg, because that's what Ffuncall takes. */
Lisp_Object *newargs;
USE_SAFE_ALLOCA;
- if (nargs == PTRDIFF_MAX)
+ ptrdiff_t nargs1;
+ if (INT_ADD_WRAPV (nargs, 1, &nargs1))
xsignal0 (Qoverflow_error);
- SAFE_ALLOCA_LISP (newargs, nargs + 1);
+ SAFE_ALLOCA_LISP (newargs, nargs1);
newargs[0] = value_to_lisp (fun);
for (ptrdiff_t i = 0; i < nargs; i++)
newargs[1 + i] = value_to_lisp (args[i]);
- emacs_value result = lisp_to_value (Ffuncall (nargs + 1, newargs));
+ emacs_value result = lisp_to_value (Ffuncall (nargs1, newargs));
SAFE_FREE ();
return result;
}
if (r != 0)
{
- if (! (MOST_NEGATIVE_FIXNUM <= r && r <= MOST_POSITIVE_FIXNUM))
+ if (FIXNUM_OVERFLOW_P (r))
xsignal0 (Qoverflow_error);
xsignal2 (Qmodule_load_failed, file, make_number (r));
}
break;
if (i == len)
{
- EMACS_INT n;
-
i = 0;
- for (n = 0; (n += str[i++] - '0') <= MOST_POSITIVE_FIXNUM; n *= 10)
+ for (EMACS_INT n = 0;
+ (n += str[i++] - '0') <= MOST_POSITIVE_FIXNUM; )
{
if (i == len)
return make_number (n);
- if (MOST_POSITIVE_FIXNUM / 10 < n)
+ if (INT_MULTIPLY_WRAPV (n, 10, &n))
break;
}
doc: /* Return the current depth in recursive edits. */)
(void)
{
- Lisp_Object temp;
- /* Wrap around reliably on integer overflow. */
- EMACS_INT sum = (command_loop_level & INTMASK) + (minibuf_level & INTMASK);
- XSETINT (temp, sum);
- return temp;
+ EMACS_INT sum;
+ INT_ADD_WRAPV (command_loop_level, minibuf_level, &sum);
+ return make_number (sum);
}
DEFUN ("open-dribble-file", Fopen_dribble_file, Sopen_dribble_file, 1, 1,
{
EMACS_INT n = 0;
Lisp_Object tem;
+ bool overflow = false;
/* Read a non-negative integer. */
while (c >= '0' && c <= '9')
{
- if (MOST_POSITIVE_FIXNUM / 10 < n
- || MOST_POSITIVE_FIXNUM < n * 10 + c - '0')
- n = MOST_POSITIVE_FIXNUM + 1;
- else
- n = n * 10 + c - '0';
+ overflow |= INT_MULTIPLY_WRAPV (n, 10, &n);
+ overflow |= INT_ADD_WRAPV (n, c - '0', &n);
c = READCHAR;
}
- if (n <= MOST_POSITIVE_FIXNUM)
+ if (!overflow && n <= MOST_POSITIVE_FIXNUM)
{
if (c == 'r' || c == 'R')
return read_integer (readcharfun, n);
return buf;
}
+/* Return the approximate percentage N is of D (rounding upward), or 99,
+ whichever is less. Assume 0 < D and 0 <= N <= D * INT_MAX / 100. */
+
+static int
+percent99 (ptrdiff_t n, ptrdiff_t d)
+{
+ int percent = (d - 1 + 100.0 * n) / d;
+ return min (percent, 99);
+}
+
/* Return a string for the output of a mode line %-spec for window W,
generated by character C. FIELD_WIDTH > 0 means pad the string
returned with spaces to that value. Return a Lisp string in
case 'p':
{
ptrdiff_t pos = marker_position (w->start);
- ptrdiff_t total = BUF_ZV (b) - BUF_BEGV (b);
+ ptrdiff_t begv = BUF_BEGV (b);
+ ptrdiff_t zv = BUF_ZV (b);
- if (w->window_end_pos <= BUF_Z (b) - BUF_ZV (b))
- {
- if (pos <= BUF_BEGV (b))
- return "All";
- else
- return "Bottom";
- }
- else if (pos <= BUF_BEGV (b))
+ if (w->window_end_pos <= BUF_Z (b) - zv)
+ return pos <= begv ? "All" : "Bottom";
+ else if (pos <= begv)
return "Top";
else
{
- if (total > 1000000)
- /* Do it differently for a large value, to avoid overflow. */
- total = ((pos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
- else
- total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total;
- /* We can't normally display a 3-digit number,
- so get us a 2-digit number that is close. */
- if (total == 100)
- total = 99;
- sprintf (decode_mode_spec_buf, "%2"pD"d%%", total);
+ sprintf (decode_mode_spec_buf, "%2d%%",
+ percent99 (pos - begv, zv - begv));
return decode_mode_spec_buf;
}
}
{
ptrdiff_t toppos = marker_position (w->start);
ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
- ptrdiff_t total = BUF_ZV (b) - BUF_BEGV (b);
+ ptrdiff_t begv = BUF_BEGV (b);
+ ptrdiff_t zv = BUF_ZV (b);
- if (botpos >= BUF_ZV (b))
- {
- if (toppos <= BUF_BEGV (b))
- return "All";
- else
- return "Bottom";
- }
+ if (zv <= botpos)
+ return toppos <= begv ? "All" : "Bottom";
else
{
- if (total > 1000000)
- /* Do it differently for a large value, to avoid overflow. */
- total = ((botpos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
- else
- total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total;
- /* We can't normally display a 3-digit number,
- so get us a 2-digit number that is close. */
- if (total == 100)
- total = 99;
- if (toppos <= BUF_BEGV (b))
- sprintf (decode_mode_spec_buf, "Top%2"pD"d%%", total);
- else
- sprintf (decode_mode_spec_buf, "%2"pD"d%%", total);
+ sprintf (decode_mode_spec_buf,
+ &"Top%2d%%"[begv < toppos ? sizeof "Top" - 1 : 0],
+ percent99 (botpos - begv, zv - begv));
return decode_mode_spec_buf;
}
}