diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2011-09-04 16:58:01 -0700 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2011-09-04 16:58:01 -0700 |
commit | 1c262cae409ec55a234c89b3b74a13a77c7f595a (patch) | |
tree | 2780610d6227a3b1f64aa9398f21501ce3de774e /src | |
parent | 7f59d9c856de33b97bc3f2708dcc8dadf24ee040 (diff) | |
parent | 052bd38a56ad14a7f311677051e778de6c4bdc1c (diff) | |
download | emacs-1c262cae409ec55a234c89b3b74a13a77c7f595a.tar.gz emacs-1c262cae409ec55a234c89b3b74a13a77c7f595a.tar.bz2 emacs-1c262cae409ec55a234c89b3b74a13a77c7f595a.zip |
Merge from trunk.
Diffstat (limited to 'src')
-rw-r--r-- | src/ChangeLog | 147 | ||||
-rw-r--r-- | src/dbusbind.c | 69 | ||||
-rw-r--r-- | src/dispnew.c | 19 | ||||
-rw-r--r-- | src/doprnt.c | 203 | ||||
-rw-r--r-- | src/editfns.c | 5 | ||||
-rw-r--r-- | src/emacs.c | 8 | ||||
-rw-r--r-- | src/eval.c | 26 | ||||
-rw-r--r-- | src/filelock.c | 35 | ||||
-rw-r--r-- | src/font.c | 203 | ||||
-rw-r--r-- | src/fontset.c | 6 | ||||
-rw-r--r-- | src/frame.c | 46 | ||||
-rw-r--r-- | src/gtkutil.c | 5 | ||||
-rw-r--r-- | src/indent.c | 12 | ||||
-rw-r--r-- | src/keyboard.c | 46 | ||||
-rw-r--r-- | src/keymap.c | 19 | ||||
-rw-r--r-- | src/lisp.h | 12 | ||||
-rw-r--r-- | src/lread.c | 16 | ||||
-rw-r--r-- | src/macros.c | 12 | ||||
-rw-r--r-- | src/macros.h | 3 | ||||
-rw-r--r-- | src/minibuf.c | 8 | ||||
-rw-r--r-- | src/nsterm.m | 2 | ||||
-rw-r--r-- | src/print.c | 37 | ||||
-rw-r--r-- | src/process.c | 6 | ||||
-rw-r--r-- | src/search.c | 10 | ||||
-rw-r--r-- | src/sysdep.c | 39 | ||||
-rw-r--r-- | src/term.c | 2 | ||||
-rw-r--r-- | src/window.c | 28 | ||||
-rw-r--r-- | src/window.h | 4 | ||||
-rw-r--r-- | src/xdisp.c | 4 | ||||
-rw-r--r-- | src/xfaces.c | 35 | ||||
-rw-r--r-- | src/xfns.c | 2 | ||||
-rw-r--r-- | src/xterm.c | 3 | ||||
-rw-r--r-- | src/xterm.h | 3 |
33 files changed, 706 insertions, 369 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index f3953630803..e730c79f65b 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,146 @@ +2011-09-04 Paul Eggert <eggert@cs.ucla.edu> + + * Makefile.in (gl-stamp): move-if-change now in build-aux (Bug#9169). + +2011-09-04 Paul Eggert <eggert@cs.ucla.edu> + + sprintf-related integer and memory overflow issues (Bug#9412). + + * doprnt.c (doprnt): Support printing ptrdiff_t and intmax_t values. + (esprintf, exprintf, evxprintf): New functions. + * keyboard.c (command_loop_level): Now EMACS_INT, not int. + (cmd_error): kbd macro iterations count is now EMACS_INT, not int. + (modify_event_symbol): Do not assume that the length of + name_alist_or_stem is safe to alloca and fits in int. + (Fexecute_extended_command): Likewise for function name and binding. + (Frecursion_depth): Wrap around reliably on integer overflow. + * keymap.c (push_key_description): First arg is now EMACS_INT, not int, + since some callers pass EMACS_INT values. + (Fsingle_key_description): Don't crash if symbol name contains more + than MAX_ALLOCA bytes. + * minibuf.c (minibuf_level): Now EMACS_INT, not int. + (get_minibuffer): Arg is now EMACS_INT, not int. + * lisp.h (get_minibuffer, push_key_description): Reflect API changes. + (esprintf, exprintf, evxprintf): New decls. + * window.h (command_loop_level, minibuf_level): Reflect API changes. + + * dbusbind.c (signature_cat): New function. + (xd_signature, Fdbus_register_signal): + Do not overrun buffer; instead, report string overflow. + + * dispnew.c (add_window_display_history): Don't overrun buffer. + Truncate instead; this is OK since it's just a log. + + * editfns.c (Fcurrent_time_zone): Don't overrun buffer + even if the time zone offset is outlandishly large. + Don't mishandle offset == INT_MIN. + + * emacs.c (main) [NS_IMPL_COCOA]: Don't overrun buffer + when creating daemon; the previous buffer-overflow check was incorrect. + + * eval.c (verror): Simplify by rewriting in terms of evxprintf, + which has the guts of the old verror function. + + * filelock.c (lock_file_1, lock_file): Don't blindly alloca long name; + use SAFE_ALLOCA instead. Use esprintf to avoid int-overflow issues. + + * font.c: Include <float.h>, for DBL_MAX_10_EXP. + (font_unparse_xlfd): Don't blindly alloca long strings. + Don't assume XINT result fits in int, or that XFLOAT_DATA * 10 + fits in int, when using sprintf. Use single snprintf to count + length of string rather than counting it via multiple sprintfs; + that's simpler and more reliable. + (font_unparse_fcname): Use it to avoid sprintf buffer overrun. + (generate_otf_features) [0 && HAVE_LIBOTF]: Use esprintf, not + sprintf, in case result does not fit in int. + + * fontset.c (num_auto_fontsets): Now printmax_t, not int. + (fontset_from_font): Print it. + + * frame.c (tty_frame_count): Now printmax_t, not int. + (make_terminal_frame, set_term_frame_name): Print it. + (x_report_frame_params): In X, window IDs are unsigned long, + not signed long, so print them as unsigned. + (validate_x_resource_name): Check for implausibly long names, + and don't assume name length fits in 'int'. + (x_get_resource_string): Don't blindly alloca invocation name; + use SAFE_ALLOCA. Use esprintf, not sprintf, in case result does + not fit in int. + + * gtkutil.c: Include <float.h>, for DBL_MAX_10_EXP. + (xg_check_special_colors, xg_set_geometry): + Make sprintf buffers a bit bigger, to avoid potential buffer overrun. + + * lread.c (dir_warning): Don't blindly alloca buffer; use SAFE_ALLOCA. + Use esprintf, not sprintf, in case result does not fit in int. + + * macros.c (executing_kbd_macro_iterations): Now EMACS_INT, not int. + (Fend_kbd_macro): Don't mishandle MOST_NEGATIVE_FIXNUM by treating + it as a large positive number. + (Fexecute_kbd_macro): Don't assume repeat count fits in int. + * macros.h (executing_kbd_macro_iterations): Now EMACS_INT, not int. + + * nsterm.m ((NSSize)windowWillResize): Use esprintf, not sprintf, + in case result does not fit in int. + + * print.c (float_to_string): Detect width overflow more reliably. + (print_object): Make sprintf buffer a bit bigger, to avoid potential + buffer overrun. Don't assume list length fits in 'int'. Treat + print length of 0 as 0, not as infinity; to be consistent with other + uses of print length in this function. Don't overflow print length + index. Don't assume hash table size fits in 'long', or that + vectorlike size fits in 'unsigned long'. + + * process.c (make_process): Use printmax_t, not int, to format + process-name gensyms. + + * sysdep.c (snprintf) [! HAVE_SNPRINTF]: New function. + + * term.c (produce_glyphless_glyph): Make sprintf buffer a bit bigger + to avoid potential buffer overrun. + + * xfaces.c (x_update_menu_appearance): Don't overrun buffer + if X resource line is longer than 512 bytes. + + * xfns.c (x_window): Make sprintf buffer a bit bigger + to avoid potential buffer overrun. + + * xterm.c (x_io_error_quitter): Don't overrun sprintf buffer. + + * xterm.h (x_check_errors): Add ATTRIBUTE_FORMAT_PRINTF. + +2011-09-04 Paul Eggert <eggert@cs.ucla.edu> + + Integer overflow fixes for scrolling, etc. + Without these, Emacs silently mishandles large integers sometimes. + For example, "C-u 4294967297 M-x recenter" was treated as if + it were "C-u 1 M-x recenter" on a typical 64-bit host. + + * xdisp.c (try_window_id): Check Emacs fixnum range before + converting to 'int'. + + * window.c (window_scroll_line_based, Frecenter): + Check that an Emacs fixnum is in range before assigning it to 'int'. + (Frecenter, Fmove_to_window_line): Use EMACS_INT, not int, for + values converted from Emacs fixnums. + (Frecenter): Don't wrap around a line count if it is out of 'int' + range; instead, treat it as an extreme value. + (Fset_window_configuration, compare_window_configurations): + Use ptrdiff_t, not int, for index that might exceed 2 GiB. + + * search.c (Freplace_match): Use ptrdiff_t, not int, for indexes + that can exceed INT_MAX. Check that EMACS_INT value is in range + before assigning it to the (possibly-narrower) index. + (match_limit): Don't assume that a fixnum can fit in 'int'. + + * print.c (print_object): Use ptrdiff_t, not int, for index that can + exceed INT_MAX. + + * indent.c (position_indentation): Now takes ptrdiff_t, not int. + (Fvertical_motion): Don't wrap around LINES values that don't fit + in 'int'. Instead, treat them as extreme values. This is good + enough for windows, which can't have more than INT_MAX lines anyway. + 2011-09-03 Lars Magne Ingebrigtsen <larsi@gnus.org> * Require libxml/parser.h to avoid compilation warning. @@ -913,10 +1056,6 @@ (re_exec): Fix return type. (regexec): Fix type of `ret'. (Bug#9203) -2011-07-29 Paul Eggert <eggert@cs.ucla.edu> - - * Makefile.in (gl-stamp): move-if-change now in build-aux (Bug#9169). - 2011-07-28 Paul Eggert <eggert@cs.ucla.edu> * image.c (check_image_size): Use 1024x1024 if unknown frame (Bug#9189). diff --git a/src/dbusbind.c b/src/dbusbind.c index 4828f4e968d..8dac2a6249f 100644 --- a/src/dbusbind.c +++ b/src/dbusbind.c @@ -259,6 +259,18 @@ xd_symbol_to_dbus_type (Lisp_Object object) } \ while (0) +/* Append to SIGNATURE a copy of X, making sure SIGNATURE does + not become too long. */ +static void +signature_cat (char *signature, char const *x) +{ + ptrdiff_t siglen = strlen (signature); + ptrdiff_t xlen = strlen (x); + if (DBUS_MAXIMUM_SIGNATURE_LENGTH - xlen <= siglen) + string_overflow (); + strcat (signature, x); +} + /* Compute SIGNATURE of OBJECT. It must have a form that it can be used in dbus_message_iter_open_container. DTYPE is the DBusType the object is related to. It is passed as argument, because it @@ -271,6 +283,8 @@ xd_signature (char *signature, unsigned int dtype, unsigned int parent_type, Lis { unsigned int subtype; Lisp_Object elt; + char const *subsig; + int subsiglen; char x[DBUS_MAXIMUM_SIGNATURE_LENGTH]; elt = object; @@ -328,12 +342,13 @@ xd_signature (char *signature, unsigned int dtype, unsigned int parent_type, Lis if (NILP (elt)) { subtype = DBUS_TYPE_STRING; - strcpy (x, DBUS_TYPE_STRING_AS_STRING); + subsig = DBUS_TYPE_STRING_AS_STRING; } else { subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt)); xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt))); + subsig = x; } /* If the element type is DBUS_TYPE_SIGNATURE, and this is the @@ -342,7 +357,7 @@ xd_signature (char *signature, unsigned int dtype, unsigned int parent_type, Lis if ((subtype == DBUS_TYPE_SIGNATURE) && STRINGP (CAR_SAFE (XD_NEXT_VALUE (elt))) && NILP (CDR_SAFE (XD_NEXT_VALUE (elt)))) - strcpy (x, SSDATA (CAR_SAFE (XD_NEXT_VALUE (elt)))); + subsig = SSDATA (CAR_SAFE (XD_NEXT_VALUE (elt))); while (!NILP (elt)) { @@ -351,7 +366,10 @@ xd_signature (char *signature, unsigned int dtype, unsigned int parent_type, Lis elt = CDR_SAFE (XD_NEXT_VALUE (elt)); } - sprintf (signature, "%c%s", dtype, x); + subsiglen = snprintf (signature, DBUS_MAXIMUM_SIGNATURE_LENGTH, + "%c%s", dtype, subsig); + if (! (0 <= subsiglen && subsiglen < DBUS_MAXIMUM_SIGNATURE_LENGTH)) + string_overflow (); break; case DBUS_TYPE_VARIANT: @@ -383,10 +401,10 @@ xd_signature (char *signature, unsigned int dtype, unsigned int parent_type, Lis { subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt)); xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt))); - strcat (signature, x); + signature_cat (signature, x); elt = CDR_SAFE (XD_NEXT_VALUE (elt)); } - strcat (signature, DBUS_STRUCT_END_CHAR_AS_STRING); + signature_cat (signature, DBUS_STRUCT_END_CHAR_AS_STRING); break; case DBUS_TYPE_DICT_ENTRY: @@ -407,7 +425,7 @@ xd_signature (char *signature, unsigned int dtype, unsigned int parent_type, Lis elt = XD_NEXT_VALUE (elt); subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt)); xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt))); - strcat (signature, x); + signature_cat (signature, x); if (!XD_BASIC_DBUS_TYPE (subtype)) wrong_type_argument (intern ("D-Bus"), CAR_SAFE (XD_NEXT_VALUE (elt))); @@ -416,14 +434,14 @@ xd_signature (char *signature, unsigned int dtype, unsigned int parent_type, Lis elt = CDR_SAFE (XD_NEXT_VALUE (elt)); subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt)); xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt))); - strcat (signature, x); + signature_cat (signature, x); if (!NILP (CDR_SAFE (XD_NEXT_VALUE (elt)))) wrong_type_argument (intern ("D-Bus"), CAR_SAFE (CDR_SAFE (XD_NEXT_VALUE (elt)))); /* Closing signature. */ - strcat (signature, DBUS_DICT_ENTRY_END_CHAR_AS_STRING); + signature_cat (signature, DBUS_DICT_ENTRY_END_CHAR_AS_STRING); break; default: @@ -2026,7 +2044,7 @@ usage: (dbus-register-signal BUS SERVICE PATH INTERFACE SIGNAL HANDLER &rest ARG DBusConnection *connection; ptrdiff_t i; char rule[DBUS_MAXIMUM_MATCH_RULE_LENGTH]; - char x[DBUS_MAXIMUM_MATCH_RULE_LENGTH]; + int rulelen; DBusError derror; /* Check parameters. */ @@ -2071,32 +2089,43 @@ usage: (dbus-register-signal BUS SERVICE PATH INTERFACE SIGNAL HANDLER &rest ARG connection = xd_initialize (bus, TRUE); /* Create a rule to receive related signals. */ - sprintf (rule, - "type='signal',interface='%s',member='%s'", - SDATA (interface), - SDATA (signal)); + rulelen = snprintf (rule, sizeof rule, + "type='signal',interface='%s',member='%s'", + SDATA (interface), + SDATA (signal)); + if (! (0 <= rulelen && rulelen < sizeof rule)) + string_overflow (); /* Add unique name and path to the rule if they are non-nil. */ if (!NILP (uname)) { - sprintf (x, ",sender='%s'", SDATA (uname)); - strcat (rule, x); + int len = snprintf (rule + rulelen, sizeof rule - rulelen, + ",sender='%s'", SDATA (uname)); + if (! (0 <= len && len < sizeof rule - rulelen)) + string_overflow (); + rulelen += len; } if (!NILP (path)) { - sprintf (x, ",path='%s'", SDATA (path)); - strcat (rule, x); + int len = snprintf (rule + rulelen, sizeof rule - rulelen, + ",path='%s'", SDATA (path)); + if (! (0 <= len && len < sizeof rule - rulelen)) + string_overflow (); + rulelen += len; } /* Add arguments to the rule if they are non-nil. */ for (i = 6; i < nargs; ++i) if (!NILP (args[i])) { + int len; CHECK_STRING (args[i]); - sprintf (x, ",arg%"pD"d='%s'", i - 6, - SDATA (args[i])); - strcat (rule, x); + len = snprintf (rule + rulelen, sizeof rule - rulelen, + ",arg%"pD"d='%s'", i - 6, SDATA (args[i])); + if (! (0 <= len && len < sizeof rule - rulelen)) + string_overflow (); + rulelen += len; } /* Add the rule to the bus. */ diff --git a/src/dispnew.c b/src/dispnew.c index e96583e0025..5c28d014819 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -272,15 +272,16 @@ add_window_display_history (struct window *w, const char *msg, int paused_p) buf = redisplay_history[history_idx].trace; ++history_idx; - sprintf (buf, "%"pMu": window %p (`%s')%s\n", - history_tick++, - w, - ((BUFFERP (w->buffer) - && STRINGP (BVAR (XBUFFER (w->buffer), name))) - ? SSDATA (BVAR (XBUFFER (w->buffer), name)) - : "???"), - paused_p ? " ***paused***" : ""); - strcat (buf, msg); + snprintf (buf, sizeof redisplay_history[0].trace, + "%"pMu": window %p (`%s')%s\n%s", + history_tick++, + w, + ((BUFFERP (w->buffer) + && STRINGP (BVAR (XBUFFER (w->buffer), name))) + ? SSDATA (BVAR (XBUFFER (w->buffer), name)) + : "???"), + paused_p ? " ***paused***" : "", + msg); } diff --git a/src/doprnt.c b/src/doprnt.c index 79f9f36e461..638fa4d6312 100644 --- a/src/doprnt.c +++ b/src/doprnt.c @@ -70,9 +70,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ %<flags><width><precision><length>character where flags is [+ -0], width is [0-9]+, precision is .[0-9]+, and length - is empty or l or the value of the pI macro. Also, %% in a format - stands for a single % in the output. A % that does not introduce a - valid %-sequence causes undefined behavior. + is empty or l or the value of the pD or pI or pMd (sans "d") macros. + Also, %% in a format stands for a single % in the output. A % that + does not introduce a valid %-sequence causes undefined behavior. The + flag character inserts a + before any positive number, while a space inserts a space before any positive number; these flags only affect %d, %o, @@ -85,8 +85,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ modifier: it is supported for %d, %o, and %x conversions of integral arguments, must immediately precede the conversion specifier, and means that the respective argument is to be treated as `long int' or `unsigned long - int'. Similarly, the value of the pI macro means to use EMACS_INT or - EMACS_UINT and the empty length modifier means `int' or `unsigned int'. + int'. Similarly, the value of the pD macro means to use ptrdiff_t, + the value of the pI macro means to use EMACS_INT or EMACS_UINT, the + value of the pMd etc. macros means to use intmax_t or uintmax_t, + and the empty length modifier means `int' or `unsigned int'. 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 @@ -173,8 +175,17 @@ doprnt (char *buffer, ptrdiff_t bufsize, const char *format, { ptrdiff_t size_bound = 0; EMACS_INT width; /* Columns occupied by STRING on display. */ - int long_flag = 0; - int pIlen = sizeof pI - 1; + enum { + pDlen = sizeof pD - 1, + pIlen = sizeof pI - 1, + pMlen = sizeof pMd - 2 + }; + enum { + no_modifier, long_modifier, pD_modifier, pI_modifier, pM_modifier + } length_modifier = no_modifier; + static char const modifier_len[] = { 0, 1, pDlen, pIlen, pMlen }; + int maxmlen = max (max (1, pDlen), max (pIlen, pMlen)); + int mlen; fmt++; /* Copy this one %-spec into fmtcpy. */ @@ -213,19 +224,26 @@ doprnt (char *buffer, ptrdiff_t bufsize, const char *format, fmt++; } - if (0 < pIlen && pIlen <= format_end - fmt - && memcmp (fmt, pI, pIlen) == 0) + /* Check for the length modifiers in textual length order, so + that longer modifiers override shorter ones. */ + for (mlen = 1; mlen <= maxmlen; mlen++) { - long_flag = 2; - memcpy (string, fmt + 1, pIlen); - string += pIlen; - fmt += pIlen; - } - else if (fmt < format_end && *fmt == 'l') - { - long_flag = 1; - *string++ = *++fmt; + if (format_end - fmt < mlen) + break; + if (mlen == 1 && *fmt == 'l') + length_modifier = long_modifier; + if (mlen == pDlen && memcmp (fmt, pD, pDlen) == 0) + length_modifier = pD_modifier; + if (mlen == pIlen && memcmp (fmt, pI, pIlen) == 0) + length_modifier = pI_modifier; + if (mlen == pMlen && memcmp (fmt, pMd, pMlen) == 0) + length_modifier = pM_modifier; } + + mlen = modifier_len[length_modifier]; + memcpy (string, fmt + 1, mlen); + string += mlen; + fmt += mlen; *string = 0; /* Make the size bound large enough to handle floating point formats @@ -252,55 +270,78 @@ doprnt (char *buffer, ptrdiff_t bufsize, const char *format, /* case 'b': */ case 'l': case 'd': - { - int i; - long l; - - if (1 < long_flag) + switch (length_modifier) + { + case no_modifier: { - EMACS_INT ll = va_arg (ap, EMACS_INT); - sprintf (sprintf_buffer, fmtcpy, ll); + int v = va_arg (ap, int); + sprintf (sprintf_buffer, fmtcpy, v); } - else if (long_flag) + break; + case long_modifier: { - l = va_arg(ap, long); - sprintf (sprintf_buffer, fmtcpy, l); + long v = va_arg (ap, long); + sprintf (sprintf_buffer, fmtcpy, v); } - else + break; + case pD_modifier: + signed_pD_modifier: { - i = va_arg(ap, int); - sprintf (sprintf_buffer, fmtcpy, i); + ptrdiff_t v = va_arg (ap, ptrdiff_t); + sprintf (sprintf_buffer, fmtcpy, v); } - /* Now copy into final output, truncating as necessary. */ - string = sprintf_buffer; - goto doit; - } + break; + case pI_modifier: + { + EMACS_INT v = va_arg (ap, EMACS_INT); + sprintf (sprintf_buffer, fmtcpy, v); + } + break; + case pM_modifier: + { + intmax_t v = va_arg (ap, intmax_t); + sprintf (sprintf_buffer, fmtcpy, v); + } + break; + } + /* Now copy into final output, truncating as necessary. */ + string = sprintf_buffer; + goto doit; case 'o': case 'x': - { - unsigned u; - unsigned long ul; - - if (1 < long_flag) + switch (length_modifier) + { + case no_modifier: { - EMACS_UINT ull = va_arg (ap, EMACS_UINT); - sprintf (sprintf_buffer, fmtcpy, ull); + unsigned v = va_arg (ap, unsigned); + sprintf (sprintf_buffer, fmtcpy, v); } - else if (long_flag) + break; + case long_modifier: { - ul = va_arg(ap, unsigned long); - sprintf (sprintf_buffer, fmtcpy, ul); + unsigned long v = va_arg (ap, unsigned long); + sprintf (sprintf_buffer, fmtcpy, v); } - else + break; + case pD_modifier: + goto signed_pD_modifier; + case pI_modifier: { - u = va_arg(ap, unsigned); - sprintf (sprintf_buffer, fmtcpy, u); + EMACS_UINT v = va_arg (ap, EMACS_UINT); + sprintf (sprintf_buffer, fmtcpy, v); } - /* Now copy into final output, truncating as necessary. */ - string = sprintf_buffer; - goto doit; - } + break; + case pM_modifier: + { + uintmax_t v = va_arg (ap, uintmax_t); + sprintf (sprintf_buffer, fmtcpy, v); + } + break; + } + /* Now copy into final output, truncating as necessary. */ + string = sprintf_buffer; + goto doit; case 'f': case 'e': @@ -426,3 +467,61 @@ doprnt (char *buffer, ptrdiff_t bufsize, const char *format, SAFE_FREE (); return bufptr - buffer; } + +/* Format to an unbounded buffer BUF. This is like sprintf, except it + is not limited to returning an 'int' so it doesn't have a silly 2 + GiB limit on typical 64-bit hosts. However, it is limited to the + Emacs-style formats that doprnt supports. + + Return the number of bytes put into BUF, excluding the terminating + '\0'. */ +ptrdiff_t +esprintf (char *buf, char const *format, ...) +{ + ptrdiff_t nbytes; + va_list ap; + va_start (ap, format); + nbytes = doprnt (buf, TYPE_MAXIMUM (ptrdiff_t), format, 0, ap); + va_end (ap); + return nbytes; +} + +/* Format to buffer *BUF of positive size *BUFSIZE, reallocating *BUF + and updating *BUFSIZE if the buffer is too small, and otherwise + behaving line esprintf. When reallocating, free *BUF unless it is + equal to NONHEAPBUF, and if BUFSIZE_MAX is nonnegative then signal + memory exhaustion instead of growing the buffer size past + BUFSIZE_MAX. */ +ptrdiff_t +exprintf (char **buf, ptrdiff_t *bufsize, + char const *nonheapbuf, ptrdiff_t bufsize_max, + char const *format, ...) +{ + ptrdiff_t nbytes; + va_list ap; + va_start (ap, format); + nbytes = evxprintf (buf, bufsize, nonheapbuf, bufsize_max, format, ap); + va_end (ap); + return nbytes; +} + +/* Act like exprintf, except take a va_list. */ +ptrdiff_t +evxprintf (char **buf, ptrdiff_t *bufsize, + char const *nonheapbuf, ptrdiff_t bufsize_max, + char const *format, va_list ap) +{ + for (;;) + { + ptrdiff_t nbytes; + va_list ap_copy; + va_copy (ap_copy, ap); + nbytes = doprnt (*buf, *bufsize, format, 0, ap_copy); + va_end (ap_copy); + if (nbytes < *bufsize - 1) + return nbytes; + if (*buf != nonheapbuf) + xfree (*buf); + *buf = xpalloc (NULL, bufsize, 1, bufsize_max, 1); + } +} diff --git a/src/editfns.c b/src/editfns.c index 6759016766f..580298c6e7d 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -2014,7 +2014,7 @@ the data it can't find. */) { int offset = tm_diff (t, &gmt); char *s = 0; - char buf[6]; + char buf[sizeof "+00" + INT_STRLEN_BOUND (int)]; #ifdef HAVE_TM_ZONE if (t->tm_zone) @@ -2029,7 +2029,8 @@ the data it can't find. */) if (!s) { /* No local time zone name is available; use "+-NNNN" instead. */ - int am = (offset < 0 ? -offset : offset) / 60; + int m = offset / 60; + int am = offset < 0 ? - m : m; sprintf (buf, "%c%02d%02d", (offset < 0 ? '-' : '+'), am/60, am%60); s = buf; } diff --git a/src/emacs.c b/src/emacs.c index 4cc476290c0..83ad8d95156 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -1072,15 +1072,17 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem if (!dname_arg || !strchr (dname_arg, '\n')) { /* In orig, child: now exec w/special daemon name. */ char fdStr[80]; + int fdStrlen = + snprintf (fdStr, sizeof fdStr, + "--daemon=\n%d,%d\n%s", daemon_pipe[0], + daemon_pipe[1], dname_arg ? dname_arg : ""); - if (dname_arg && strlen (dname_arg) > 70) + if (! (0 <= fdStrlen && fdStrlen < sizeof fdStr)) { fprintf (stderr, "daemon: child name too long\n"); exit (1); } - sprintf (fdStr, "--daemon=\n%d,%d\n%s", daemon_pipe[0], - daemon_pipe[1], dname_arg ? dname_arg : ""); argv[skip_args] = fdStr; execv (argv[0], argv); diff --git a/src/eval.c b/src/eval.c index e722b53fb72..f2407cede31 100644 --- a/src/eval.c +++ b/src/eval.c @@ -1951,35 +1951,11 @@ verror (const char *m, va_list ap) char buf[4000]; ptrdiff_t size = sizeof buf; ptrdiff_t size_max = STRING_BYTES_BOUND + 1; - char const *m_end = m + strlen (m); char *buffer = buf; ptrdiff_t used; Lisp_Object string; - while (1) - { - va_list ap_copy; - va_copy (ap_copy, ap); - 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 - excluding the terminating null byte, and it always terminates with a - null byte, even when producing a truncated message. */ - if (used < size - 1) - break; - if (size <= size_max / 2) - size *= 2; - else if (size < size_max) - size = size_max; - else - break; /* and leave the message truncated */ - - if (buffer != buf) - xfree (buffer); - buffer = (char *) xmalloc (size); - } - + used = evxprintf (&buffer, &size, buf, size_max, m, ap); string = make_string (buffer, used); if (buffer != buf) xfree (buffer); diff --git a/src/filelock.c b/src/filelock.c index c28ee7837fa..7235c862ef0 100644 --- a/src/filelock.c +++ b/src/filelock.c @@ -341,6 +341,9 @@ lock_file_1 (char *lfname, int force) const char *user_name; const char *host_name; char *lock_info_str; + ptrdiff_t lock_info_size; + int symlink_errno; + USE_SAFE_ALLOCA; /* Call this first because it can GC. */ boot = get_boot_time (); @@ -353,17 +356,14 @@ lock_file_1 (char *lfname, int force) host_name = SSDATA (Fsystem_name ()); else host_name = ""; - lock_info_str = (char *)alloca (strlen (user_name) + strlen (host_name) - + 2 * INT_STRLEN_BOUND (printmax_t) - + sizeof "@.:"); + lock_info_size = (strlen (user_name) + strlen (host_name) + + 2 * INT_STRLEN_BOUND (printmax_t) + + sizeof "@.:"); + SAFE_ALLOCA (lock_info_str, char *, lock_info_size); pid = getpid (); - if (boot) - sprintf (lock_info_str, "%s@%s.%"pMd":%"pMd, - user_name, host_name, pid, boot); - else - sprintf (lock_info_str, "%s@%s.%"pMd, - user_name, host_name, pid); + esprintf (lock_info_str, boot ? "%s@%s.%"pMd":%"pMd : "%s@%s.%"pMd, + user_name, host_name, pid, boot); err = symlink (lock_info_str, lfname); if (errno == EEXIST && force) @@ -372,6 +372,9 @@ lock_file_1 (char *lfname, int force) err = symlink (lock_info_str, lfname); } + symlink_errno = errno; + SAFE_FREE (); + errno = symlink_errno; return err == 0; } @@ -541,9 +544,11 @@ lock_file (Lisp_Object fn) { register Lisp_Object attack, orig_fn, encoded_fn; register char *lfname, *locker; + ptrdiff_t locker_size; lock_info_type lock_info; printmax_t pid; struct gcpro gcpro1; + USE_SAFE_ALLOCA; /* Don't do locking while dumping Emacs. Uncompressing wtmp files uses call-process, which does not work @@ -580,15 +585,17 @@ lock_file (Lisp_Object fn) return; /* Else consider breaking the lock */ - locker = (char *) alloca (strlen (lock_info.user) + strlen (lock_info.host) - + INT_STRLEN_BOUND (printmax_t) - + sizeof "@ (pid )"); + locker_size = (strlen (lock_info.user) + strlen (lock_info.host) + + INT_STRLEN_BOUND (printmax_t) + + sizeof "@ (pid )"); + SAFE_ALLOCA (locker, char *, locker_size); pid = lock_info.pid; - sprintf (locker, "%s@%s (pid %"pMd")", - lock_info.user, lock_info.host, pid); + esprintf (locker, "%s@%s (pid %"pMd")", + lock_info.user, lock_info.host, pid); FREE_LOCK_INFO (lock_info); attack = call2 (intern ("ask-user-about-lock"), fn, build_string (locker)); + SAFE_FREE (); if (!NILP (attack)) /* User says take the lock */ { diff --git a/src/font.c b/src/font.c index 5f8d22157d6..34cacb37ce4 100644 --- a/src/font.c +++ b/src/font.c @@ -21,6 +21,7 @@ You should have received a copy of the GNU General Public License along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <config.h> +#include <float.h> #include <stdio.h> #include <ctype.h> #include <setjmp.h> @@ -1180,7 +1181,7 @@ font_unparse_xlfd (Lisp_Object font, int pixel_size, char *name, int nbytes) char *p; const char *f[XLFD_REGISTRY_INDEX + 1]; Lisp_Object val; - int i, j, len = 0; + int i, j, len; font_assert (FONTP (font)); @@ -1195,9 +1196,9 @@ font_unparse_xlfd (Lisp_Object font, int pixel_size, char *name, int nbytes) if (NILP (val)) { if (j == XLFD_REGISTRY_INDEX) - f[j] = "*-*", len += 4; + f[j] = "*-*"; else - f[j] = "*", len += 2; + f[j] = "*"; } else { @@ -1207,21 +1208,15 @@ font_unparse_xlfd (Lisp_Object font, int pixel_size, char *name, int nbytes) && ! strchr (SSDATA (val), '-')) { /* Change "jisx0208*" and "jisx0208" to "jisx0208*-*". */ - if (SDATA (val)[SBYTES (val) - 1] == '*') - { - f[j] = p = alloca (SBYTES (val) + 3); - sprintf (p, "%s-*", SDATA (val)); - len += SBYTES (val) + 3; - } - else - { - f[j] = p = alloca (SBYTES (val) + 4); - sprintf (p, "%s*-*", SDATA (val)); - len += SBYTES (val) + 4; - } + ptrdiff_t alloc = SBYTES (val) + 4; + if (nbytes <= alloc) + return -1; + f[j] = p = alloca (alloc); + sprintf (p, "%s%s-*", SDATA (val), + "*" + (SDATA (val)[SBYTES (val) - 1] == '*')); } else - f[j] = SSDATA (val), len += SBYTES (val) + 1; + f[j] = SSDATA (val); } } @@ -1230,11 +1225,11 @@ font_unparse_xlfd (Lisp_Object font, int pixel_size, char *name, int nbytes) { val = font_style_symbolic (font, i, 0); if (NILP (val)) - f[j] = "*", len += 2; + f[j] = "*"; else { val = SYMBOL_NAME (val); - f[j] = SSDATA (val), len += SBYTES (val) + 1; + f[j] = SSDATA (val); } } @@ -1242,64 +1237,62 @@ font_unparse_xlfd (Lisp_Object font, int pixel_size, char *name, int nbytes) font_assert (NUMBERP (val) || NILP (val)); if (INTEGERP (val)) { - i = XINT (val); - if (i <= 0) - i = pixel_size; - if (i > 0) + EMACS_INT v = XINT (val); + if (v <= 0) + v = pixel_size; + if (v > 0) { - f[XLFD_PIXEL_INDEX] = p = alloca (22); - len += sprintf (p, "%d-*", i) + 1; + f[XLFD_PIXEL_INDEX] = p = + alloca (sizeof "-*" + INT_STRLEN_BOUND (EMACS_INT)); + sprintf (p, "%"pI"d-*", v); } else - f[XLFD_PIXEL_INDEX] = "*-*", len += 4; + f[XLFD_PIXEL_INDEX] = "*-*"; } else if (FLOATP (val)) { - i = XFLOAT_DATA (val) * 10; - f[XLFD_PIXEL_INDEX] = p = alloca (12); - len += sprintf (p, "*-%d", i) + 1; + double v = XFLOAT_DATA (val) * 10; + f[XLFD_PIXEL_INDEX] = p = alloca (sizeof "*-" + 1 + DBL_MAX_10_EXP + 1); + sprintf (p, "*-%.0f", v); } else - f[XLFD_PIXEL_INDEX] = "*-*", len += 4; + f[XLFD_PIXEL_INDEX] = "*-*"; if (INTEGERP (AREF (font, FONT_DPI_INDEX))) { - i = XINT (AREF (font, FONT_DPI_INDEX)); - f[XLFD_RESX_INDEX] = p = alloca (22); - len += sprintf (p, "%d-%d", i, i) + 1; + EMACS_INT v = XINT (AREF (font, FONT_DPI_INDEX)); + f[XLFD_RESX_INDEX] = p = + alloca (sizeof "-" + 2 * INT_STRLEN_BOUND (EMACS_INT)); + sprintf (p, "%"pI"d-%"pI"d", v, v); } else - f[XLFD_RESX_INDEX] = "*-*", len += 4; + f[XLFD_RESX_INDEX] = "*-*"; if (INTEGERP (AREF (font, FONT_SPACING_INDEX))) { - int spacing = XINT (AREF (font, FONT_SPACING_INDEX)); + EMACS_INT spacing = XINT (AREF (font, FONT_SPACING_INDEX)); f[XLFD_SPACING_INDEX] = (spacing <= FONT_SPACING_PROPORTIONAL ? "p" : spacing <= FONT_SPACING_DUAL ? "d" : spacing <= FONT_SPACING_MONO ? "m" : "c"); - len += 2; } else - f[XLFD_SPACING_INDEX] = "*", len += 2; + f[XLFD_SPACING_INDEX] = "*"; if (INTEGERP (AREF (font, FONT_AVGWIDTH_INDEX))) { - f[XLFD_AVGWIDTH_INDEX] = p = alloca (22); - len += sprintf (p, "%"pI"d", - XINT (AREF (font, FONT_AVGWIDTH_INDEX))) + 1; + f[XLFD_AVGWIDTH_INDEX] = p = alloca (INT_BUFSIZE_BOUND (EMACS_INT)); + sprintf (p, "%"pI"d", XINT (AREF (font, FONT_AVGWIDTH_INDEX))); } else - f[XLFD_AVGWIDTH_INDEX] = "*", len += 2; - len++; /* for terminating '\0'. */ - if (len >= nbytes) - return -1; - return sprintf (name, "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s", + f[XLFD_AVGWIDTH_INDEX] = "*"; + len = snprintf (name, nbytes, "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s", f[XLFD_FOUNDRY_INDEX], f[XLFD_FAMILY_INDEX], f[XLFD_WEIGHT_INDEX], f[XLFD_SLANT_INDEX], f[XLFD_SWIDTH_INDEX], f[XLFD_ADSTYLE_INDEX], f[XLFD_PIXEL_INDEX], f[XLFD_RESX_INDEX], f[XLFD_SPACING_INDEX], f[XLFD_AVGWIDTH_INDEX], f[XLFD_REGISTRY_INDEX]); + return len < nbytes ? len : -1; } /* Parse NAME (null terminated) and store information in FONT @@ -1553,23 +1546,19 @@ int font_unparse_fcname (Lisp_Object font, int pixel_size, char *name, int nbytes) { Lisp_Object family, foundry; - Lisp_Object tail, val; + Lisp_Object val; int point_size; int i; - ptrdiff_t len = 1; char *p; + char *lim; Lisp_Object styles[3]; const char *style_names[3] = { "weight", "slant", "width" }; - char work[256]; family = AREF (font, FONT_FAMILY_INDEX); if (! NILP (family)) { if (SYMBOLP (family)) - { - family = SYMBOL_NAME (family); - len += SBYTES (family); - } + family = SYMBOL_NAME (family); else family = Qnil; } @@ -1580,7 +1569,6 @@ font_unparse_fcname (Lisp_Object font, int pixel_size, char *name, int nbytes) if (XINT (val) != 0) pixel_size = XINT (val); point_size = -1; - len += 21; /* for ":pixelsize=NUM" */ } else { @@ -1588,80 +1576,91 @@ font_unparse_fcname (Lisp_Object font, int pixel_size, char *name, int nbytes) abort (); pixel_size = -1; point_size = (int) XFLOAT_DATA (val); - len += 11; /* for "-NUM" */ } foundry = AREF (font, FONT_FOUNDRY_INDEX); if (! NILP (foundry)) { if (SYMBOLP (foundry)) - { - foundry = SYMBOL_NAME (foundry); - len += 9 + SBYTES (foundry); /* ":foundry=NAME" */ - } + foundry = SYMBOL_NAME (foundry); else foundry = Qnil; } for (i = 0; i < 3; i++) - { - styles[i] = font_style_symbolic (font, FONT_WEIGHT_INDEX + i, 0); - if (! NILP (styles[i])) - len += sprintf (work, ":%s=%s", style_names[i], - SDATA (SYMBOL_NAME (styles[i]))); - } - - if (INTEGERP (AREF (font, FONT_DPI_INDEX))) - len += sprintf (work, ":dpi=%"pI"d", XINT (AREF (font, FONT_DPI_INDEX))); - if (INTEGERP (AREF (font, FONT_SPACING_INDEX))) - len += strlen (":spacing=100"); - if (INTEGERP (AREF (font, FONT_AVGWIDTH_INDEX))) - len += strlen (":scalable=false"); /* or ":scalable=true" */ - for (tail = AREF (font, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail)) - { - Lisp_Object key = XCAR (XCAR (tail)), value = XCDR (XCAR (tail)); - - len += SBYTES (SYMBOL_NAME (key)) + 1; /* for :KEY= */ - if (STRINGP (value)) - len += SBYTES (value); - else if (INTEGERP (value)) - len += sprintf (work, "%"pI"d", XINT (value)); - else if (SYMBOLP (value)) - len += (NILP (value) ? 5 : 4); /* for "false" or "true" */ - } + styles[i] = font_style_symbolic (font, FONT_WEIGHT_INDEX + i, 0); - if (len > nbytes) - return -1; p = name; + lim = name + nbytes; if (! NILP (family)) - p += sprintf (p, "%s", SDATA (family)); + { + int len = snprintf (p, lim - p, "%s", SSDATA (family)); + if (! (0 <= len && len < lim - p)) + return -1; + p += len; + } if (point_size > 0) { - if (p == name) - p += sprintf (p, "%d", point_size); - else - p += sprintf (p, "-%d", point_size); + int len = snprintf (p, lim - p, "-%d" + (p == name), point_size); + if (! (0 <= len && len < lim - p)) + return -1; + p += len; } else if (pixel_size > 0) - p += sprintf (p, ":pixelsize=%d", pixel_size); + { + int len = snprintf (p, lim - p, ":pixelsize=%d", pixel_size); + if (! (0 <= len && len < lim - p)) + return -1; + p += len; + } if (! NILP (AREF (font, FONT_FOUNDRY_INDEX))) - p += sprintf (p, ":foundry=%s", - SDATA (SYMBOL_NAME (AREF (font, FONT_FOUNDRY_INDEX)))); + { + int len = snprintf (p, lim - p, ":foundry=%s", + SSDATA (SYMBOL_NAME (AREF (font, + FONT_FOUNDRY_INDEX)))); + if (! (0 <= len && len < lim - p)) + return -1; + p += len; + } for (i = 0; i < 3; i++) if (! NILP (styles[i])) - p += sprintf (p, ":%s=%s", style_names[i], - SDATA (SYMBOL_NAME (styles[i]))); + { + int len = snprintf (p, lim - p, ":%s=%s", style_names[i], + SSDATA (SYMBOL_NAME (styles[i]))); + if (! (0 <= len && len < lim - p)) + return -1; + p += len; + } + if (INTEGERP (AREF (font, FONT_DPI_INDEX))) - p += sprintf (p, ":dpi=%"pI"d", XINT (AREF (font, FONT_DPI_INDEX))); + { + int len = snprintf (p, lim - p, ":dpi=%"pI"d", + XINT (AREF (font, FONT_DPI_INDEX))); + if (! (0 <= len && len < lim - p)) + return -1; + p += len; + } + if (INTEGERP (AREF (font, FONT_SPACING_INDEX))) - p += sprintf (p, ":spacing=%"pI"d", XINT (AREF (font, FONT_SPACING_INDEX))); + { + int len = snprintf (p, lim - p, ":spacing=%"pI"d", + XINT (AREF (font, FONT_SPACING_INDEX))); + if (! (0 <= len && len < lim - p)) + return -1; + p += len; + } + if (INTEGERP (AREF (font, FONT_AVGWIDTH_INDEX))) { - if (XINT (AREF (font, FONT_AVGWIDTH_INDEX)) == 0) - p += sprintf (p, ":scalable=true"); - else - p += sprintf (p, ":scalable=false"); + int len = snprintf (p, lim - p, + (XINT (AREF (font, FONT_AVGWIDTH_INDEX)) == 0 + ? ":scalable=true" + : ":scalable=false")); + if (! (0 <= len && len < lim - p)) + return -1; + p += len; } + return (p - name); } @@ -1952,12 +1951,12 @@ generate_otf_features (Lisp_Object spec, char *features) else if (! asterisk) { val = SYMBOL_NAME (val); - p += sprintf (p, "%s", SDATA (val)); + p += esprintf (p, "%s", SDATA (val)); } else { val = SYMBOL_NAME (val); - p += sprintf (p, "~%s", SDATA (val)); + p += esprintf (p, "~%s", SDATA (val)); } } if (CONSP (spec)) diff --git a/src/fontset.c b/src/fontset.c index c8ae1e74848..74a25a1ca04 100644 --- a/src/fontset.c +++ b/src/fontset.c @@ -1700,7 +1700,7 @@ FONT-SPEC is a vector, a cons, or a string. See the documentation of static Lisp_Object auto_fontset_alist; /* Number of automatically created fontsets. */ -static int num_auto_fontsets; +static printmax_t num_auto_fontsets; /* Retun a fontset synthesized from FONT-OBJECT. This is called from x_new_font when FONT-OBJECT is used for the default ASCII font of a @@ -1727,9 +1727,9 @@ fontset_from_font (Lisp_Object font_object) alias = intern ("fontset-startup"); else { - char temp[32]; + char temp[sizeof "fontset-auto" + INT_STRLEN_BOUND (printmax_t)]; - sprintf (temp, "fontset-auto%d", num_auto_fontsets - 1); + sprintf (temp, "fontset-auto%"pMd, num_auto_fontsets - 1); alias = intern (temp); } fontset_spec = copy_font_spec (font_spec); diff --git a/src/frame.c b/src/frame.c index 711109a70c6..66b857a73e9 100644 --- a/src/frame.c +++ b/src/frame.c @@ -497,7 +497,7 @@ make_minibuffer_frame (void) /* Construct a frame that refers to a terminal. */ -static int tty_frame_count; +static printmax_t tty_frame_count; struct frame * make_initial_frame (void) @@ -551,7 +551,7 @@ make_terminal_frame (struct terminal *terminal) { register struct frame *f; Lisp_Object frame; - char name[20]; + char name[sizeof "F" + INT_STRLEN_BOUND (printmax_t)]; if (!terminal->name) error ("Terminal is not live, can't create new frames on it"); @@ -562,7 +562,7 @@ make_terminal_frame (struct terminal *terminal) Vframe_list = Fcons (frame, Vframe_list); tty_frame_count++; - sprintf (name, "F%d", tty_frame_count); + sprintf (name, "F%"pMd, tty_frame_count); f->name = build_string (name); f->visible = 1; /* FRAME_SET_VISIBLE wd set frame_garbaged. */ @@ -2074,7 +2074,7 @@ set_term_frame_name (struct frame *f, Lisp_Object name) /* If NAME is nil, set the name to F<num>. */ if (NILP (name)) { - char namebuf[20]; + char namebuf[sizeof "F" + INT_STRLEN_BOUND (printmax_t)]; /* Check for no change needed in this very common case before we do any consing. */ @@ -2083,7 +2083,7 @@ set_term_frame_name (struct frame *f, Lisp_Object name) return; tty_frame_count++; - sprintf (namebuf, "F%d", tty_frame_count); + sprintf (namebuf, "F%"pMd, tty_frame_count); name = build_string (namebuf); } else @@ -3065,6 +3065,7 @@ x_report_frame_params (struct frame *f, Lisp_Object *alistptr) { char buf[16]; Lisp_Object tem; + unsigned long w; /* Represent negative positions (off the top or left screen edge) in a way that Fmodify_frame_parameters will understand correctly. */ @@ -3097,7 +3098,8 @@ x_report_frame_params (struct frame *f, Lisp_Object *alistptr) for non-toolkit scroll bar. ruler-mode.el depends on this. */ : Qnil)); - sprintf (buf, "%ld", (long) FRAME_X_WINDOW (f)); + w = FRAME_X_WINDOW (f); + sprintf (buf, "%lu", w); store_in_alist (alistptr, Qwindow_id, build_string (buf)); #ifdef HAVE_X_WINDOWS @@ -3105,7 +3107,10 @@ x_report_frame_params (struct frame *f, Lisp_Object *alistptr) /* Tooltip frame may not have this widget. */ if (FRAME_X_OUTPUT (f)->widget) #endif - sprintf (buf, "%ld", (long) FRAME_OUTER_WINDOW (f)); + { + w = FRAME_OUTER_WINDOW (f); + sprintf (buf, "%lu", w); + } store_in_alist (alistptr, Qouter_window_id, build_string (buf)); #endif @@ -3576,13 +3581,13 @@ x_set_alpha (struct frame *f, Lisp_Object arg, Lisp_Object oldval) void validate_x_resource_name (void) { - int len = 0; + ptrdiff_t len = 0; /* Number of valid characters in the resource name. */ - int good_count = 0; + ptrdiff_t good_count = 0; /* Number of invalid characters in the resource name. */ - int bad_count = 0; + ptrdiff_t bad_count = 0; Lisp_Object new; - int i; + ptrdiff_t i; if (!STRINGP (Vx_resource_class)) Vx_resource_class = build_string (EMACS_CLASS); @@ -3615,8 +3620,9 @@ validate_x_resource_name (void) if (bad_count == 0) return; - /* If name is entirely invalid, or nearly so, use `emacs'. */ - if (good_count < 2) + /* If name is entirely invalid, or nearly so, or is so implausibly + large that alloca might not work, use `emacs'. */ + if (good_count < 2 || MAX_ALLOCA - sizeof ".customization" < len) { Vx_resource_name = build_string ("emacs"); return; @@ -3745,20 +3751,24 @@ x_get_resource_string (const char *attribute, const char *class) { char *name_key; char *class_key; + char *result; struct frame *sf = SELECTED_FRAME (); + ptrdiff_t invocation_namelen = SBYTES (Vinvocation_name); + USE_SAFE_ALLOCA; /* Allocate space for the components, the dots which separate them, and the final '\0'. */ - name_key = (char *) alloca (SBYTES (Vinvocation_name) - + strlen (attribute) + 2); + SAFE_ALLOCA (name_key, char *, invocation_namelen + strlen (attribute) + 2); class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1) + strlen (class) + 2); - sprintf (name_key, "%s.%s", SSDATA (Vinvocation_name), attribute); + esprintf (name_key, "%s.%s", SSDATA (Vinvocation_name), attribute); sprintf (class_key, "%s.%s", EMACS_CLASS, class); - return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf)->xrdb, - name_key, class_key); + result = x_get_string_resource (FRAME_X_DISPLAY_INFO (sf)->xrdb, + name_key, class_key); + SAFE_FREE (); + return result; } #endif diff --git a/src/gtkutil.c b/src/gtkutil.c index c39119c8151..c154797735e 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -20,6 +20,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <config.h> #ifdef USE_GTK +#include <float.h> #include <signal.h> #include <stdio.h> #include <setjmp.h> @@ -567,7 +568,7 @@ xg_check_special_colors (struct frame *f, GtkStyleContext *gsty = gtk_widget_get_style_context (FRAME_GTK_OUTER_WIDGET (f)); GdkRGBA col; - char buf[64]; + char buf[sizeof "rgbi://" + 3 * (DBL_MAX_10_EXP + sizeof "-1.000000" - 1)]; int state = GTK_STATE_FLAG_SELECTED|GTK_STATE_FLAG_FOCUSED; if (get_fg) gtk_style_context_get_color (gsty, state, &col); @@ -797,7 +798,7 @@ xg_set_geometry (FRAME_PTR f) int xneg = f->size_hint_flags & XNegative; int top = f->top_pos; int yneg = f->size_hint_flags & YNegative; - char geom_str[32]; + char geom_str[sizeof "=x--" + 4 * INT_STRLEN_BOUND (int)]; if (xneg) left = -left; diff --git a/src/indent.c b/src/indent.c index 313315e9081..6e602d28f60 100644 --- a/src/indent.c +++ b/src/indent.c @@ -56,7 +56,7 @@ EMACS_INT last_known_column_point; static int last_known_column_modified; static EMACS_INT current_column_1 (void); -static EMACS_INT position_indentation (int); +static EMACS_INT position_indentation (ptrdiff_t); /* Cache of beginning of line found by the last call of current_column. */ @@ -855,7 +855,7 @@ following any initial whitespace. */) } static EMACS_INT -position_indentation (register int pos_byte) +position_indentation (ptrdiff_t pos_byte) { register EMACS_INT column = 0; int tab_width = SANE_TAB_WIDTH (current_buffer); @@ -2063,7 +2063,7 @@ whether or not it is currently displayed in some window. */) /* Do this even if LINES is 0, so that we move back to the beginning of the current line as we ought. */ if (XINT (lines) == 0 || IT_CHARPOS (it) > 0) - move_it_by_lines (&it, XINT (lines)); + move_it_by_lines (&it, max (INT_MIN, XINT (lines))); } else { @@ -2083,7 +2083,7 @@ whether or not it is currently displayed in some window. */) && it.c == '\n')) move_it_by_lines (&it, -1); it.vpos = 0; - move_it_by_lines (&it, XINT (lines)); + move_it_by_lines (&it, min (INT_MAX, XINT (lines))); } else { @@ -2099,12 +2099,12 @@ whether or not it is currently displayed in some window. */) move_it_by_lines (&it, 1); } if (XINT (lines) > 1) - move_it_by_lines (&it, XINT (lines) - 1); + move_it_by_lines (&it, min (INT_MAX, XINT (lines) - 1)); } else { it.vpos = 0; - move_it_by_lines (&it, XINT (lines)); + move_it_by_lines (&it, min (INT_MAX, XINT (lines))); } } } diff --git a/src/keyboard.c b/src/keyboard.c index ab93e0ccd24..51eac369e7c 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -196,7 +196,7 @@ int immediate_quit; int quit_char; /* Current depth in recursive edits. */ -int command_loop_level; +EMACS_INT command_loop_level; /* If not Qnil, this is a switch-frame event which we decided to put off until the end of a key sequence. This should be read as the @@ -998,7 +998,8 @@ static Lisp_Object cmd_error (Lisp_Object data) { Lisp_Object old_level, old_length; - char macroerror[50]; + char macroerror[sizeof "After..kbd macro iterations: " + + INT_STRLEN_BOUND (EMACS_INT)]; #ifdef HAVE_WINDOW_SYSTEM if (display_hourglass_p) @@ -1010,7 +1011,7 @@ cmd_error (Lisp_Object data) if (executing_kbd_macro_iterations == 1) sprintf (macroerror, "After 1 kbd macro iteration: "); else - sprintf (macroerror, "After %d kbd macro iterations: ", + sprintf (macroerror, "After %"pI"d kbd macro iterations: ", executing_kbd_macro_iterations); } else @@ -6463,11 +6464,15 @@ modify_event_symbol (EMACS_INT symbol_num, unsigned int modifiers, Lisp_Object s value = Fcdr_safe (Fassq (symbol_int, name_alist_or_stem)); else if (STRINGP (name_alist_or_stem)) { - int len = SBYTES (name_alist_or_stem); - char *buf = (char *) alloca (len + 50); - sprintf (buf, "%s-%"pI"d", SDATA (name_alist_or_stem), - XINT (symbol_int) + 1); + char *buf; + ptrdiff_t len = (SBYTES (name_alist_or_stem) + + sizeof "-" + INT_STRLEN_BOUND (EMACS_INT)); + USE_SAFE_ALLOCA; + SAFE_ALLOCA (buf, char *, len); + esprintf (buf, "%s-%"pI"d", SDATA (name_alist_or_stem), + XINT (symbol_int) + 1); value = intern (buf); + SAFE_FREE (); } else if (name_table != 0 && name_table[symbol_num]) value = intern (name_table[symbol_num]); @@ -6483,7 +6488,7 @@ modify_event_symbol (EMACS_INT symbol_num, unsigned int modifiers, Lisp_Object s if (NILP (value)) { - char buf[20]; + char buf[sizeof "key-" + INT_STRLEN_BOUND (EMACS_INT)]; sprintf (buf, "key-%"pI"d", symbol_num); value = intern (buf); } @@ -10382,19 +10387,21 @@ give to the command you invoke, if it asks for an argument. */) char *newmessage; int message_p = push_message (); int count = SPECPDL_INDEX (); + ptrdiff_t newmessage_len, newmessage_alloc; + USE_SAFE_ALLOCA; record_unwind_protect (pop_message_unwind, Qnil); binding = Fkey_description (bindings, Qnil); - - newmessage - = (char *) alloca (SCHARS (SYMBOL_NAME (function)) - + SBYTES (binding) - + 100); - sprintf (newmessage, "You can run the command `%s' with %s", - SDATA (SYMBOL_NAME (function)), - SDATA (binding)); + newmessage_alloc = + (sizeof "You can run the command `' with " + + SBYTES (SYMBOL_NAME (function)) + SBYTES (binding)); + SAFE_ALLOCA (newmessage, char *, newmessage_alloc); + newmessage_len = + esprintf (newmessage, "You can run the command `%s' with %s", + SDATA (SYMBOL_NAME (function)), + SDATA (binding)); message2 (newmessage, - strlen (newmessage), + newmessage_len, STRING_MULTIBYTE (binding)); if (NUMBERP (Vsuggest_key_bindings)) waited = sit_for (Vsuggest_key_bindings, 0, 2); @@ -10404,6 +10411,7 @@ give to the command you invoke, if it asks for an argument. */) if (!NILP (waited) && message_p) restore_message (); + SAFE_FREE (); unbind_to (count, Qnil); } } @@ -10633,7 +10641,9 @@ DEFUN ("recursion-depth", Frecursion_depth, Srecursion_depth, 0, 0, 0, (void) { Lisp_Object temp; - XSETFASTINT (temp, command_loop_level + minibuf_level); + /* Wrap around reliably on integer overflow. */ + EMACS_INT sum = (command_loop_level & INTMASK) + (minibuf_level & INTMASK); + XSETINT (temp, sum); return temp; } diff --git a/src/keymap.c b/src/keymap.c index 32b531daac4..4485080db21 100644 --- a/src/keymap.c +++ b/src/keymap.c @@ -2143,12 +2143,12 @@ spaces are put between sequence elements, etc. */) char * -push_key_description (register unsigned int c, register char *p, int force_multibyte) +push_key_description (EMACS_INT ch, char *p, int force_multibyte) { - unsigned c2; + int c, c2; /* Clear all the meaningless bits above the meta bit. */ - c &= meta_modifier | ~ - meta_modifier; + c = ch & (meta_modifier | ~ - meta_modifier); c2 = c & ~(alt_modifier | ctrl_modifier | hyper_modifier | meta_modifier | shift_modifier | super_modifier); @@ -2283,10 +2283,15 @@ around function keys and event symbols. */) { if (NILP (no_angles)) { - char *buffer - = (char *) alloca (SBYTES (SYMBOL_NAME (key)) + 5); - sprintf (buffer, "<%s>", SDATA (SYMBOL_NAME (key))); - return build_string (buffer); + char *buffer; + Lisp_Object result; + USE_SAFE_ALLOCA; + SAFE_ALLOCA (buffer, char *, + sizeof "<>" + SBYTES (SYMBOL_NAME (key))); + esprintf (buffer, "<%s>", SDATA (SYMBOL_NAME (key))); + result = build_string (buffer); + SAFE_FREE (); + return result; } else return Fsymbol_name (key); diff --git a/src/lisp.h b/src/lisp.h index 99555118047..5c84bb8e06e 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -2895,6 +2895,14 @@ extern void syms_of_print (void); /* Defined in doprnt.c */ extern ptrdiff_t doprnt (char *, ptrdiff_t, const char *, const char *, va_list); +extern ptrdiff_t esprintf (char *, char const *, ...) + ATTRIBUTE_FORMAT_PRINTF (2, 3); +extern ptrdiff_t exprintf (char **, ptrdiff_t *, char const *, ptrdiff_t, + char const *, ...) + ATTRIBUTE_FORMAT_PRINTF (5, 6); +extern ptrdiff_t evxprintf (char **, ptrdiff_t *, char const *, ptrdiff_t, + char const *, va_list) + ATTRIBUTE_FORMAT_PRINTF (5, 0); /* Defined in lread.c. */ extern Lisp_Object Qvariable_documentation, Qstandard_input; @@ -3186,7 +3194,7 @@ EXFUN (Fread_minibuffer, 2); EXFUN (Feval_minibuffer, 2); EXFUN (Fread_string, 5); EXFUN (Fassoc_string, 3); -extern Lisp_Object get_minibuffer (int); +extern Lisp_Object get_minibuffer (EMACS_INT); extern void init_minibuf_once (void); extern void syms_of_minibuf (void); @@ -3250,7 +3258,7 @@ extern void force_auto_save_soon (void); extern void init_keyboard (void); extern void syms_of_keyboard (void); extern void keys_of_keyboard (void); -extern char *push_key_description (unsigned int, char *, int); +extern char *push_key_description (EMACS_INT, char *, int); /* Defined in indent.c */ diff --git a/src/lread.c b/src/lread.c index d24da729df6..ec65e881b0e 100644 --- a/src/lread.c +++ b/src/lread.c @@ -4295,14 +4295,20 @@ init_lread (void) void dir_warning (const char *format, Lisp_Object dirname) { - char *buffer - = (char *) alloca (SCHARS (dirname) + strlen (format) + 5); - fprintf (stderr, format, SDATA (dirname)); - sprintf (buffer, format, SDATA (dirname)); + /* Don't log the warning before we've initialized!! */ if (initialized) - message_dolog (buffer, strlen (buffer), 0, STRING_MULTIBYTE (dirname)); + { + char *buffer; + ptrdiff_t message_len; + USE_SAFE_ALLOCA; + SAFE_ALLOCA (buffer, char *, + SBYTES (dirname) + strlen (format) - (sizeof "%s" - 1) + 1); + message_len = esprintf (buffer, format, SDATA (dirname)); + message_dolog (buffer, message_len, 0, STRING_MULTIBYTE (dirname)); + SAFE_FREE (); + } } void diff --git a/src/macros.c b/src/macros.c index f6cd3a3ccad..4ecf49834a1 100644 --- a/src/macros.c +++ b/src/macros.c @@ -35,7 +35,7 @@ static Lisp_Object Qkbd_macro_termination_hook; This is not bound at each level, so after an error, it describes the innermost interrupted macro. */ -int executing_kbd_macro_iterations; +EMACS_INT executing_kbd_macro_iterations; /* This is the macro that was executing. This is not bound at each level, @@ -175,11 +175,11 @@ each iteration of the macro. Iteration stops if LOOPFUNC returns nil. */) if (XFASTINT (repeat) == 0) Fexecute_kbd_macro (KVAR (current_kboard, Vlast_kbd_macro), repeat, loopfunc); - else + else if (XINT (repeat) > 1) { XSETINT (repeat, XINT (repeat)-1); - if (XINT (repeat) > 0) - Fexecute_kbd_macro (KVAR (current_kboard, Vlast_kbd_macro), repeat, loopfunc); + Fexecute_kbd_macro (KVAR (current_kboard, Vlast_kbd_macro), + repeat, loopfunc); } return Qnil; } @@ -302,9 +302,9 @@ each iteration of the macro. Iteration stops if LOOPFUNC returns nil. */) Lisp_Object final; Lisp_Object tem; int pdlcount = SPECPDL_INDEX (); - int repeat = 1; + EMACS_INT repeat = 1; struct gcpro gcpro1, gcpro2; - int success_count = 0; + EMACS_INT success_count = 0; executing_kbd_macro_iterations = 0; diff --git a/src/macros.h b/src/macros.h index 32a97e457e8..7a5d532fbb7 100644 --- a/src/macros.h +++ b/src/macros.h @@ -22,7 +22,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ This is not bound at each level, so after an error, it describes the innermost interrupted macro. */ -extern int executing_kbd_macro_iterations; +extern EMACS_INT executing_kbd_macro_iterations; /* This is the macro that was executing. This is not bound at each level, @@ -42,4 +42,3 @@ extern void finalize_kbd_macro_chars (void); /* Store a character into kbd macro being defined */ extern void store_kbd_macro_char (Lisp_Object); - diff --git a/src/minibuf.c b/src/minibuf.c index eb564a10ec6..ad8f3ed8b86 100644 --- a/src/minibuf.c +++ b/src/minibuf.c @@ -49,7 +49,7 @@ static Lisp_Object minibuf_save_list; /* Depth in minibuffer invocations. */ -int minibuf_level; +EMACS_INT minibuf_level; /* The maximum length of a minibuffer history. */ @@ -772,10 +772,10 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt, used for nonrecursive minibuffer invocations. */ Lisp_Object -get_minibuffer (int depth) +get_minibuffer (EMACS_INT depth) { Lisp_Object tail, num, buf; - char name[24]; + char name[sizeof " *Minibuf-*" + INT_STRLEN_BOUND (EMACS_INT)]; XSETFASTINT (num, depth); tail = Fnthcdr (num, Vminibuffer_list); @@ -787,7 +787,7 @@ get_minibuffer (int depth) buf = Fcar (tail); if (NILP (buf) || NILP (BVAR (XBUFFER (buf), name))) { - sprintf (name, " *Minibuf-%d*", depth); + sprintf (name, " *Minibuf-%"pI"d*", depth); buf = Fget_buffer_create (build_string (name)); /* Although the buffer's name starts with a space, undo should be diff --git a/src/nsterm.m b/src/nsterm.m index 4c9574c35ba..827404a2974 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -5316,7 +5316,7 @@ ns_term_shutdown (int sig) strcpy (old_title, t); } size_title = xmalloc (strlen (old_title) + 40); - sprintf (size_title, "%s — (%d x %d)", old_title, cols, rows); + esprintf (size_title, "%s — (%d x %d)", old_title, cols, rows); [window setTitle: [NSString stringWithUTF8String: size_title]]; [window display]; xfree (size_title); diff --git a/src/print.c b/src/print.c index 35f89860843..d67149a40ab 100644 --- a/src/print.c +++ b/src/print.c @@ -1016,12 +1016,15 @@ float_to_string (char *buf, double data) { width = 0; do - width = (width * 10) + (*cp++ - '0'); + { + width = (width * 10) + (*cp++ - '0'); + if (DBL_DIG < width) + goto lose; + } while (*cp >= '0' && *cp <= '9'); /* A precision of zero is valid only for %f. */ - if (width > DBL_DIG - || (width == 0 && *cp != 'f')) + if (width == 0 && *cp != 'f') goto lose; } @@ -1314,7 +1317,9 @@ print_prune_string_charset (Lisp_Object string) static void print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag) { - char buf[40]; + char buf[max (sizeof "from..to..in " + 2 * INT_STRLEN_BOUND (EMACS_INT), + max (sizeof " . #" + INT_STRLEN_BOUND (printmax_t), + 40))]; QUIT; @@ -1614,8 +1619,7 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag PRINTCHAR ('('); { - EMACS_INT print_length; - int i; + printmax_t i, print_length; Lisp_Object halftail = obj; /* Negative values of print-length are invalid in CL. @@ -1623,7 +1627,7 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag if (NATNUMP (Vprint_length)) print_length = XFASTINT (Vprint_length); else - print_length = 0; + print_length = TYPE_MAXIMUM (printmax_t); i = 0; while (CONSP (obj)) @@ -1634,7 +1638,7 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag /* Simple but imcomplete way. */ if (i != 0 && EQ (obj, halftail)) { - sprintf (buf, " . #%d", i / 2); + sprintf (buf, " . #%"pMd, i / 2); strout (buf, -1, -1, printcharfun); goto end_of_list; } @@ -1654,15 +1658,16 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag } } - if (i++) + if (i) PRINTCHAR (' '); - if (print_length && i > print_length) + if (print_length <= i) { strout ("...", 3, 3, printcharfun); goto end_of_list; } + i++; print_object (XCAR (obj), printcharfun, escapeflag); obj = XCDR (obj); @@ -1697,7 +1702,7 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag } else if (BOOL_VECTOR_P (obj)) { - register int i; + ptrdiff_t i; register unsigned char c; struct gcpro gcpro1; EMACS_INT size_in_chars @@ -1798,19 +1803,17 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag PRINTCHAR (' '); strout (SDATA (SYMBOL_NAME (h->weak)), -1, -1, printcharfun); PRINTCHAR (' '); - sprintf (buf, "%ld/%ld", (long) h->count, - (long) ASIZE (h->next)); + sprintf (buf, "%"pI"d/%"pI"d", h->count, ASIZE (h->next)); strout (buf, -1, -1, printcharfun); } - sprintf (buf, " 0x%lx", (unsigned long) h); + sprintf (buf, " %p", h); strout (buf, -1, -1, printcharfun); PRINTCHAR ('>'); #endif /* Implement a readable output, e.g.: #s(hash-table size 2 test equal data (k1 v1 k2 v2)) */ /* Always print the size. */ - sprintf (buf, "#s(hash-table size %ld", - (long) ASIZE (h->next)); + sprintf (buf, "#s(hash-table size %"pI"d", ASIZE (h->next)); strout (buf, -1, -1, printcharfun); if (!NILP (h->test)) @@ -2038,7 +2041,7 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag if (MISCP (obj)) sprintf (buf, "(MISC 0x%04x)", (int) XMISCTYPE (obj)); else if (VECTORLIKEP (obj)) - sprintf (buf, "(PVEC 0x%08lx)", (unsigned long) ASIZE (obj)); + sprintf (buf, "(PVEC 0x%08"pI"x)", ASIZE (obj)); else sprintf (buf, "(0x%02x)", (int) XTYPE (obj)); strout (buf, -1, -1, printcharfun); diff --git a/src/process.c b/src/process.c index a8088322147..058ad5f871f 100644 --- a/src/process.c +++ b/src/process.c @@ -616,8 +616,8 @@ make_process (Lisp_Object name) { register Lisp_Object val, tem, name1; register struct Lisp_Process *p; - char suffix[10]; - register int i; + char suffix[sizeof "<>" + INT_STRLEN_BOUND (printmax_t)]; + printmax_t i; p = allocate_process (); @@ -651,7 +651,7 @@ make_process (Lisp_Object name) { tem = Fget_process (name1); if (NILP (tem)) break; - sprintf (suffix, "<%d>", i); + sprintf (suffix, "<%"pMd">", i); name1 = concat2 (name, build_string (suffix)); } name = name1; diff --git a/src/search.c b/src/search.c index d892792cbaa..b3d67e6c431 100644 --- a/src/search.c +++ b/src/search.c @@ -2404,7 +2404,7 @@ since only regular expressions have distinguished subexpressions. */) int some_uppercase; int some_nonuppercase_initial; register int c, prevc; - int sub; + ptrdiff_t sub; EMACS_INT opoint, newpoint; CHECK_STRING (newtext); @@ -2423,9 +2423,9 @@ since only regular expressions have distinguished subexpressions. */) else { CHECK_NUMBER (subexp); - sub = XINT (subexp); - if (sub < 0 || sub >= search_regs.num_regs) + if (! (0 <= XINT (subexp) && XINT (subexp) < search_regs.num_regs)) args_out_of_range (subexp, make_number (search_regs.num_regs)); + sub = XINT (subexp); } if (NILP (string)) @@ -2662,7 +2662,7 @@ since only regular expressions have distinguished subexpressions. */) unsigned char str[MAX_MULTIBYTE_LENGTH]; const unsigned char *add_stuff = NULL; ptrdiff_t add_len = 0; - int idx = -1; + ptrdiff_t idx = -1; if (str_multibyte) { @@ -2813,7 +2813,7 @@ since only regular expressions have distinguished subexpressions. */) static Lisp_Object match_limit (Lisp_Object num, int beginningp) { - register int n; + EMACS_INT n; CHECK_NUMBER (num); n = XINT (num); diff --git a/src/sysdep.c b/src/sysdep.c index 57fff94f552..e20bd591da1 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -1811,6 +1811,45 @@ strerror (int errnum) } #endif /* not WINDOWSNT */ #endif /* ! HAVE_STRERROR */ + +#ifndef HAVE_SNPRINTF +/* Approximate snprintf as best we can on ancient hosts that lack it. */ +int +snprintf (char *buf, size_t bufsize, char const *format, ...) +{ + ptrdiff_t size = min (bufsize, PTRDIFF_MAX); + ptrdiff_t nbytes = size - 1; + va_list ap; + + if (size) + { + va_start (ap, format); + nbytes = doprnt (buf, size, format, 0, ap); + va_end (ap); + } + + if (nbytes == size - 1) + { + /* Calculate the length of the string that would have been created + had the buffer been large enough. */ + char stackbuf[4000]; + char *b = stackbuf; + ptrdiff_t bsize = sizeof stackbuf; + va_start (ap, format); + nbytes = evxprintf (&b, &bsize, stackbuf, -1, format, ap); + va_end (ap); + if (b != stackbuf) + xfree (b); + } + + if (INT_MAX < nbytes) + { + errno = EOVERFLOW; + return -1; + } + return nbytes; +} +#endif int emacs_open (const char *path, int oflag, int mode) diff --git a/src/term.c b/src/term.c index 837ab399152..10416090b80 100644 --- a/src/term.c +++ b/src/term.c @@ -1817,7 +1817,7 @@ produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym) { int face_id; int len; - char buf[9]; + char buf[sizeof "\\x" + max (6, (sizeof it->c * CHAR_BIT + 3) / 4)]; char const *str = " "; /* Get a face ID for the glyph by utilizing a cache (the same way as diff --git a/src/window.c b/src/window.c index 96b1144acf2..e3850387a64 100644 --- a/src/window.c +++ b/src/window.c @@ -4662,14 +4662,9 @@ window_scroll_line_based (Lisp_Object window, int n, int whole, int noerror) if (pos < ZV) { - int this_scroll_margin = scroll_margin; - /* Don't use a scroll margin that is negative or too large. */ - if (this_scroll_margin < 0) - this_scroll_margin = 0; - - if (XINT (w->total_lines) < 4 * scroll_margin) - this_scroll_margin = XINT (w->total_lines) / 4; + int this_scroll_margin = + max (0, min (scroll_margin, XINT (w->total_lines) / 4)); set_marker_restricted_both (w->start, w->buffer, pos, pos_byte); w->start_at_line_beg = bolp; @@ -5057,7 +5052,7 @@ and redisplay normally--don't erase and redraw the frame. */) struct buffer *obuf = current_buffer; int center_p = 0; EMACS_INT charpos, bytepos; - int iarg IF_LINT (= 0); + EMACS_INT iarg IF_LINT (= 0); int this_scroll_margin; /* If redisplay is suppressed due to an error, try again. */ @@ -5096,9 +5091,8 @@ and redisplay normally--don't erase and redraw the frame. */) /* Do this after making BUF current in case scroll_margin is buffer-local. */ - this_scroll_margin = max (0, scroll_margin); - this_scroll_margin = min (this_scroll_margin, - XFASTINT (w->total_lines) / 4); + this_scroll_margin = + max (0, min (scroll_margin, XFASTINT (w->total_lines) / 4)); /* Handle centering on a graphical frame specially. Such frames can have variable-height lines and centering point on the basis of @@ -5122,7 +5116,7 @@ and redisplay normally--don't erase and redraw the frame. */) { struct it it; struct text_pos pt; - int nlines = -iarg; + int nlines = min (INT_MAX, -iarg); int extra_line_spacing; int h = window_box_height (w); void *itdata = bidi_shelve_cache (); @@ -5288,15 +5282,14 @@ zero means top of window, negative means relative to bottom of window. */) lines = displayed_window_lines (w); #if 0 - this_scroll_margin = max (0, scroll_margin); - this_scroll_margin = min (this_scroll_margin, lines / 4); + this_scroll_margin = max (0, min (scroll_margin, lines / 4)); #endif if (NILP (arg)) XSETFASTINT (arg, lines / 2); else { - int iarg = XINT (Fprefix_numeric_value (arg)); + EMACS_INT iarg = XINT (Fprefix_numeric_value (arg)); if (iarg < 0) iarg = iarg + lines; @@ -5468,7 +5461,8 @@ the return value is nil. Otherwise the value is t. */) struct window *root_window; struct window **leaf_windows; int n_leaf_windows; - int k, i, n; + ptrdiff_t k; + int i, n; /* If the frame has been resized since this window configuration was made, we change the frame to the size specified in the @@ -6344,7 +6338,7 @@ compare_window_configurations (Lisp_Object configuration1, Lisp_Object configura { register struct save_window_data *d1, *d2; struct Lisp_Vector *sws1, *sws2; - int i; + ptrdiff_t i; CHECK_WINDOW_CONFIGURATION (configuration1); CHECK_WINDOW_CONFIGURATION (configuration2); diff --git a/src/window.h b/src/window.h index 485734e907e..c6fa5e7a338 100644 --- a/src/window.h +++ b/src/window.h @@ -847,11 +847,11 @@ extern Lisp_Object echo_area_window; /* Depth in recursive edits. */ -extern int command_loop_level; +extern EMACS_INT command_loop_level; /* Depth in minibuffer invocations. */ -extern int minibuf_level; +extern EMACS_INT minibuf_level; /* true if we should redraw the mode lines on the next redisplay. */ diff --git a/src/xdisp.c b/src/xdisp.c index 1716cc82188..f11362c1ae6 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -16919,8 +16919,8 @@ try_window_id (struct window *w) { int this_scroll_margin, cursor_height; - this_scroll_margin = max (0, scroll_margin); - this_scroll_margin = min (this_scroll_margin, WINDOW_TOTAL_LINES (w) / 4); + this_scroll_margin = + max (0, min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4)); this_scroll_margin *= FRAME_LINE_HEIGHT (it.f); cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height; diff --git a/src/xfaces.c b/src/xfaces.c index 431ca07b8df..47d55f4da4b 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -3549,6 +3549,8 @@ x_update_menu_appearance (struct frame *f) rdb != NULL)) { char line[512]; + char *buf = line; + ptrdiff_t bufsize = sizeof line; Lisp_Object lface = lface_from_face_name (f, Qmenu, 1); struct face *face = FACE_FROM_ID (f, MENU_FACE_ID); const char *myname = SSDATA (Vx_resource_name); @@ -3561,24 +3563,25 @@ x_update_menu_appearance (struct frame *f) if (STRINGP (LFACE_FOREGROUND (lface))) { - sprintf (line, "%s.%s*foreground: %s", - myname, popup_path, - SDATA (LFACE_FOREGROUND (lface))); + exprintf (&buf, &bufsize, line, -1, "%s.%s*foreground: %s", + myname, popup_path, + SDATA (LFACE_FOREGROUND (lface))); XrmPutLineResource (&rdb, line); - sprintf (line, "%s.pane.menubar*foreground: %s", - myname, SDATA (LFACE_FOREGROUND (lface))); + exprintf (&buf, &bufsize, line, -1, "%s.pane.menubar*foreground: %s", + myname, SDATA (LFACE_FOREGROUND (lface))); XrmPutLineResource (&rdb, line); changed_p = 1; } if (STRINGP (LFACE_BACKGROUND (lface))) { - sprintf (line, "%s.%s*background: %s", - myname, popup_path, - SDATA (LFACE_BACKGROUND (lface))); + exprintf (&buf, &bufsize, line, -1, "%s.%s*background: %s", + myname, popup_path, + SDATA (LFACE_BACKGROUND (lface))); XrmPutLineResource (&rdb, line); - sprintf (line, "%s.pane.menubar*background: %s", - myname, SDATA (LFACE_BACKGROUND (lface))); + + exprintf (&buf, &bufsize, line, -1, "%s.pane.menubar*background: %s", + myname, SDATA (LFACE_BACKGROUND (lface))); XrmPutLineResource (&rdb, line); changed_p = 1; } @@ -3616,11 +3619,12 @@ x_update_menu_appearance (struct frame *f) #else char *fontsetname = SSDATA (xlfd); #endif - sprintf (line, "%s.pane.menubar*font%s: %s", - myname, suffix, fontsetname); + exprintf (&buf, &bufsize, line, -1, "%s.pane.menubar*font%s: %s", + myname, suffix, fontsetname); XrmPutLineResource (&rdb, line); - sprintf (line, "%s.%s*font%s: %s", - myname, popup_path, suffix, fontsetname); + + exprintf (&buf, &bufsize, line, -1, "%s.%s*font%s: %s", + myname, popup_path, suffix, fontsetname); XrmPutLineResource (&rdb, line); changed_p = 1; if (fontsetname != SSDATA (xlfd)) @@ -3630,6 +3634,9 @@ x_update_menu_appearance (struct frame *f) if (changed_p && f->output_data.x->menubar_widget) free_frame_menubar (f); + + if (buf != line) + xfree (buf); } } diff --git a/src/xfns.c b/src/xfns.c index 9a3d5fcda83..194a8f063b7 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -2440,7 +2440,7 @@ x_window (struct frame *f, long window_prompting, int minibuffer_only) /* Do some needed geometry management. */ { ptrdiff_t len; - char *tem, shell_position[32]; + char *tem, shell_position[sizeof "=x++" + 4 * INT_STRLEN_BOUND (int)]; Arg gal[10]; int gac = 0; int extra_borders = 0; diff --git a/src/xterm.c b/src/xterm.c index c07caec6c78..86393cf411f 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -7900,7 +7900,8 @@ x_io_error_quitter (Display *display) { char buf[256]; - sprintf (buf, "Connection lost to X server `%s'", DisplayString (display)); + snprintf (buf, sizeof buf, "Connection lost to X server `%s'", + DisplayString (display)); x_connection_closed (display, buf); return 0; } diff --git a/src/xterm.h b/src/xterm.h index 30867656710..fe86a32d09f 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -955,7 +955,8 @@ XrmDatabase x_load_resources (Display *, const char *, const char *, extern int x_text_icon (struct frame *, const char *); extern int x_bitmap_icon (struct frame *, Lisp_Object); extern void x_catch_errors (Display *); -extern void x_check_errors (Display *, const char *); +extern void x_check_errors (Display *, const char *) + ATTRIBUTE_FORMAT_PRINTF (2, 0); extern int x_had_errors_p (Display *); extern int x_catching_errors (void); extern void x_uncatch_errors (void); |