Merge from trunk.
authorPaul Eggert <eggert@cs.ucla.edu>
Sun, 4 Sep 2011 23:58:01 +0000 (16:58 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Sun, 4 Sep 2011 23:58:01 +0000 (16:58 -0700)
52 files changed:
ChangeLog
configure.in
doc/emacs/ChangeLog
doc/emacs/basic.texi
lib-src/ChangeLog
lib-src/emacsclient.c
lib-src/etags.c
lib-src/movemail.c
lib-src/update-game-score.c
lisp/ChangeLog
lisp/gnus/ChangeLog
lisp/gnus/gnus-art.el
lisp/gnus/gnus-score.el
lisp/gnus/gnus-spec.el
lisp/gnus/gnus.el
lisp/net/tramp-sh.el
lisp/net/tramp.el
nt/ChangeLog
nt/config.nt
src/ChangeLog
src/dbusbind.c
src/dispnew.c
src/doprnt.c
src/editfns.c
src/emacs.c
src/eval.c
src/filelock.c
src/font.c
src/fontset.c
src/frame.c
src/gtkutil.c
src/indent.c
src/keyboard.c
src/keymap.c
src/lisp.h
src/lread.c
src/macros.c
src/macros.h
src/minibuf.c
src/nsterm.m
src/print.c
src/process.c
src/search.c
src/sysdep.c
src/term.c
src/window.c
src/window.h
src/xdisp.c
src/xfaces.c
src/xfns.c
src/xterm.c
src/xterm.h

index f760b7b..ab2bf75 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,4 @@
-2011-09-03  Paul Eggert  <eggert@cs.ucla.edu>
+2011-09-04  Paul Eggert  <eggert@cs.ucla.edu>
 
        Merge from gnulib, using build-aux to remove clutter (Bug#9169).
        * autogen/README: Update destination list.
        'configure'.
        * make-dist: Adjust to new build-aux and build-aux/snippit dirs.
 
+2011-09-04  Paul Eggert  <eggert@cs.ucla.edu>
+
+       * configure.in (snprintf): New check.
+
 2011-08-30  Paul Eggert  <eggert@cs.ucla.edu>
 
        * configure.in (opsys): Change pattern to *-*-linux*
index 6d35975..a892978 100644 (file)
@@ -3072,6 +3072,8 @@ fi
 
 AC_FUNC_FORK
 
+AC_CHECK_FUNCS(snprintf)
+
 dnl Adapted from Haible's version.
 AC_CACHE_CHECK([for nl_langinfo and CODESET], emacs_cv_langinfo_codeset,
   [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <langinfo.h>]],
index 2407d7d..5695841 100644 (file)
@@ -1,3 +1,7 @@
+2011-09-04  Eli Zaretskii  <eliz@gnu.org>
+
+       * basic.texi (Inserting Text): Add index entries.  (Bug#9433)
+
 2011-08-29  Chong Yidong  <cyd@stupidchicken.com>
 
        * modes.texi (Choosing Modes): auto-mode-case-fold is now t.
index edf0785..b06391f 100644 (file)
@@ -101,7 +101,9 @@ character to insert (@pxref{Arguments}).
 
 @findex ucs-insert
 @kindex C-x 8 RET
-@cindex Unicode
+@cindex Unicode characters, inserting
+@cindex insert Unicode character
+@cindex characters, inserting by name or code-point
   Instead of @kbd{C-q}, you can use @kbd{C-x 8 @key{RET}}
 (@code{ucs-insert}) to insert a character based on its Unicode name or
 code-point.  This command prompts for a character to insert, using
index 00876d2..4207364 100644 (file)
@@ -1,8 +1,43 @@
-2011-07-28  Paul Eggert  <eggert@cs.ucla.edu>
+2011-09-04  Paul Eggert  <eggert@cs.ucla.edu>
 
        * Makefile.in ($(DESTDIR)${archlibdir}): install-sh moved
        to build-aux (Bug#9169).
 
+2011-09-04  Paul Eggert  <eggert@cs.ucla.edu>
+
+       Integer and memory overflow issues (Bug#9397).
+
+       * emacsclient.c (xmalloc): Accept size_t, not unsigned int, to
+       avoid potential buffer overflow issues on typical 64-bit hosts.
+       Return void *, not long *.
+       (get_current_dir_name): Report a failure, instead of looping
+       forever, if buffer size calculation overflows.  Treat malloc
+       failures like realloc failures, as that has better behavior and is
+       more consistent.  Do not check whether xmalloc returns NULL, as
+       that's not possible.
+       (message): Do not arbitrarily truncate message to 2048 bytes when
+       sending it to stderr; use vfprintf instead.
+       (get_server_config, set_local_socket)
+       (start_daemon_and_retry_set_socket): Do not alloca
+       arbitrarily-large buffers; that's not safe.
+       (get_server_config, set_local_socket): Do not use sprintf when its
+       result might not fit in 'int'.
+       (set_local_socket): Do not assume uid fits in 'int'.
+
+       * etags.c (xmalloc, xrealloc): Accept size_t, not unsigned int,
+       to avoid potential buffer overflow issues on typical 64-bit hosts.
+       (whatlen_max): New static var.
+       (main): Avoid buffer overflow if subsidiary command length is
+       greater than BUFSIZ or 2*BUFSIZ + 20. Do not use sprintf when its
+       result might not fit in 'int'.
+
+       * movemail.c (main): Do not use sprintf when its result might not fit
+       in 'int'.  Instead, put the possibly-long file name into the
+       output of pfatal_with_name.
+
+       * update-game-score.c: Include <limits.h>
+       (get_user_id): Do not assume uid fits in 'int'.  Simplify.
+
 2011-07-28  Paul Eggert  <eggert@cs.ucla.edu>
 
        Assume freestanding C89 headers, string.h, stdlib.h.
index 2af139a..ece9dc6 100644 (file)
@@ -194,10 +194,10 @@ struct option longopts[] =
 \f
 /* Like malloc but get fatal error if memory is exhausted.  */
 
-static long *
-xmalloc (unsigned int size)
+static void *
+xmalloc (size_t size)
 {
-  long *result = (long *) malloc (size);
+  void *result = malloc (size);
   if (result == NULL)
     {
       perror ("malloc");
@@ -250,32 +250,33 @@ get_current_dir_name (void)
       )
     {
       buf = (char *) xmalloc (strlen (pwd) + 1);
-      if (!buf)
-        return NULL;
       strcpy (buf, pwd);
     }
 #ifdef HAVE_GETCWD
   else
     {
       size_t buf_size = 1024;
-      buf = (char *) xmalloc (buf_size);
-      if (!buf)
-        return NULL;
       for (;;)
         {
+         int tmp_errno;
+         buf = malloc (buf_size);
+         if (! buf)
+           break;
           if (getcwd (buf, buf_size) == buf)
             break;
-          if (errno != ERANGE)
+         tmp_errno = errno;
+         free (buf);
+         if (tmp_errno != ERANGE)
             {
-              int tmp_errno = errno;
-              free (buf);
               errno = tmp_errno;
               return NULL;
             }
           buf_size *= 2;
-          buf = (char *) realloc (buf, buf_size);
-          if (!buf)
-            return NULL;
+         if (! buf_size)
+           {
+             errno = ENOMEM;
+             return NULL;
+           }
         }
     }
 #else
@@ -283,8 +284,6 @@ get_current_dir_name (void)
     {
       /* We need MAXPATHLEN here.  */
       buf = (char *) xmalloc (MAXPATHLEN + 1);
-      if (!buf)
-        return NULL;
       if (getwd (buf) == NULL)
         {
           int tmp_errno = errno;
@@ -494,16 +493,17 @@ static void message (int, const char *, ...) ATTRIBUTE_FORMAT_PRINTF (2, 3);
 static void
 message (int is_error, const char *format, ...)
 {
-  char msg[2048];
   va_list args;
 
   va_start (args, format);
-  vsprintf (msg, format, args);
-  va_end (args);
 
 #ifdef WINDOWSNT
   if (w32_window_app ())
     {
+      char msg[2048];
+      vsnprintf (msg, sizeof msg, format, args);
+      msg[sizeof msg - 1] = '\0';
+
       if (is_error)
        MessageBox (NULL, msg, "Emacsclient ERROR", MB_ICONERROR);
       else
@@ -514,9 +514,11 @@ message (int is_error, const char *format, ...)
     {
       FILE *f = is_error ? stderr : stdout;
 
-      fputs (msg, f);
+      vfprintf (f, format, args);
       fflush (f);
     }
+
+  va_end (args);
 }
 
 /* Decode the options from argv and argc.
@@ -959,18 +961,24 @@ get_server_config (struct sockaddr_in *server, char *authentication)
 
       if (home)
         {
-          char *path = alloca (strlen (home) + strlen (server_file)
-                              + EXTRA_SPACE);
-          sprintf (path, "%s/.emacs.d/server/%s", home, server_file);
+         char *path = xmalloc (strlen (home) + strlen (server_file)
+                               + EXTRA_SPACE);
+         strcpy (path, home);
+         strcat (path, "/.emacs.d/server/");
+         strcat (path, server_file);
           config = fopen (path, "rb");
+         free (path);
         }
 #ifdef WINDOWSNT
       if (!config && (home = egetenv ("APPDATA")))
         {
-          char *path = alloca (strlen (home) + strlen (server_file)
-                              + EXTRA_SPACE);
-          sprintf (path, "%s/.emacs.d/server/%s", home, server_file);
+         char *path = xmalloc (strlen (home) + strlen (server_file)
+                               + EXTRA_SPACE);
+         strcpy (path, home);
+         strcat (path, "/.emacs.d/server/");
+         strcat (path, server_file);
           config = fopen (path, "rb");
+         free (path);
         }
 #endif
     }
@@ -1243,6 +1251,8 @@ set_local_socket (void)
     int saved_errno = 0;
     const char *server_name = "server";
     const char *tmpdir IF_LINT ( = NULL);
+    char *tmpdir_storage = NULL;
+    char *socket_name_storage = NULL;
 
     if (socket_name && !strchr (socket_name, '/')
        && !strchr (socket_name, '\\'))
@@ -1255,6 +1265,8 @@ set_local_socket (void)
 
     if (default_sock)
       {
+       long uid = geteuid ();
+       ptrdiff_t tmpdirlen;
        tmpdir = egetenv ("TMPDIR");
        if (!tmpdir)
           {
@@ -1265,17 +1277,19 @@ set_local_socket (void)
             size_t n = confstr (_CS_DARWIN_USER_TEMP_DIR, NULL, (size_t) 0);
             if (n > 0)
               {
-                tmpdir = alloca (n);
+               tmpdir = tmpdir_storage = xmalloc (n);
                 confstr (_CS_DARWIN_USER_TEMP_DIR, tmpdir, n);
               }
             else
 #endif
               tmpdir = "/tmp";
           }
-       socket_name = alloca (strlen (tmpdir) + strlen (server_name)
-                             + EXTRA_SPACE);
-       sprintf (socket_name, "%s/emacs%d/%s",
-                tmpdir, (int) geteuid (), server_name);
+       tmpdirlen = strlen (tmpdir);
+       socket_name = socket_name_storage =
+         xmalloc (tmpdirlen + strlen (server_name) + EXTRA_SPACE);
+       strcpy (socket_name, tmpdir);
+       sprintf (socket_name + tmpdirlen, "/emacs%ld/", uid);
+       strcat (socket_name + tmpdirlen, server_name);
       }
 
     if (strlen (socket_name) < sizeof (server.sun_path))
@@ -1309,10 +1323,13 @@ set_local_socket (void)
            if (pw && (pw->pw_uid != geteuid ()))
              {
                /* We're running under su, apparently. */
-               socket_name = alloca (strlen (tmpdir) + strlen (server_name)
-                                     + EXTRA_SPACE);
-               sprintf (socket_name, "%s/emacs%d/%s",
-                        tmpdir, (int) pw->pw_uid, server_name);
+               long uid = pw->pw_uid;
+               ptrdiff_t tmpdirlen = strlen (tmpdir);
+               socket_name = xmalloc (tmpdirlen + strlen (server_name)
+                                      + EXTRA_SPACE);
+               strcpy (socket_name, tmpdir);
+               sprintf (socket_name + tmpdirlen, "/emacs%ld/", uid);
+               strcat (socket_name + tmpdirlen, server_name);
 
                if (strlen (socket_name) < sizeof (server.sun_path))
                  strcpy (server.sun_path, socket_name);
@@ -1322,6 +1339,7 @@ set_local_socket (void)
                             progname, socket_name);
                    exit (EXIT_FAILURE);
                  }
+               free (socket_name);
 
                sock_status = socket_status (server.sun_path);
                 saved_errno = errno;
@@ -1331,6 +1349,9 @@ set_local_socket (void)
          }
       }
 
+    free (socket_name_storage);
+    free (tmpdir_storage);
+
     switch (sock_status)
       {
       case 1:
@@ -1526,8 +1547,8 @@ start_daemon_and_retry_set_socket (void)
        {
          /* Pass  --daemon=socket_name as argument.  */
          const char *deq = "--daemon=";
-         char *daemon_arg = alloca (strlen (deq)
-                                    + strlen (socket_name) + 1);
+         char *daemon_arg = xmalloc (strlen (deq)
+                                     + strlen (socket_name) + 1);
          strcpy (daemon_arg, deq);
          strcat (daemon_arg, socket_name);
          d_argv[1] = daemon_arg;
index 522c54e..9d92056 100644 (file)
@@ -414,8 +414,8 @@ static bool filename_is_absolute (char *f);
 static void canonicalize_filename (char *);
 static void linebuffer_init (linebuffer *);
 static void linebuffer_setlen (linebuffer *, int);
-static PTR xmalloc (unsigned int);
-static PTR xrealloc (char *, unsigned int);
+static PTR xmalloc (size_t);
+static PTR xrealloc (char *, size_t);
 
 \f
 static char searchar = '/';    /* use /.../ searches */
@@ -425,6 +425,7 @@ static char *progname;              /* name this program was invoked with */
 static char *cwd;              /* current working directory */
 static char *tagfiledir;       /* directory of tagfile */
 static FILE *tagf;             /* ioptr for tags file */
+static ptrdiff_t whatlen_max;  /* maximum length of any 'what' member */
 
 static fdesc *fdhead;          /* head of file description list */
 static fdesc *curfdp;          /* current file description */
@@ -1066,6 +1067,7 @@ main (int argc, char **argv)
   int current_arg, file_count;
   linebuffer filename_lb;
   bool help_asked = FALSE;
+  ptrdiff_t len;
  char *optstring;
  int opt;
 
@@ -1110,6 +1112,9 @@ main (int argc, char **argv)
        /* This means that a file name has been seen.  Record it. */
        argbuffer[current_arg].arg_type = at_filename;
        argbuffer[current_arg].what     = optarg;
+       len = strlen (optarg);
+       if (whatlen_max < len)
+         whatlen_max = len;
        ++current_arg;
        ++file_count;
        break;
@@ -1118,6 +1123,9 @@ main (int argc, char **argv)
        /* Parse standard input.  Idea by Vivek <vivek@etla.org>. */
        argbuffer[current_arg].arg_type = at_stdin;
        argbuffer[current_arg].what     = optarg;
+       len = strlen (optarg);
+       if (whatlen_max < len)
+         whatlen_max = len;
        ++current_arg;
        ++file_count;
        if (parsing_stdin)
@@ -1160,6 +1168,9 @@ main (int argc, char **argv)
       case 'r':
        argbuffer[current_arg].arg_type = at_regexp;
        argbuffer[current_arg].what = optarg;
+       len = strlen (optarg);
+       if (whatlen_max < len)
+         whatlen_max = len;
        ++current_arg;
        break;
       case 'R':
@@ -1198,6 +1209,9 @@ main (int argc, char **argv)
     {
       argbuffer[current_arg].arg_type = at_filename;
       argbuffer[current_arg].what = argv[optind];
+      len = strlen (argv[optind]);
+      if (whatlen_max < len)
+       whatlen_max = len;
       ++current_arg;
       ++file_count;
     }
@@ -1331,7 +1345,9 @@ main (int argc, char **argv)
   /* From here on, we are in (CTAGS && !cxref_style) */
   if (update)
     {
-      char cmd[BUFSIZ];
+      char *cmd =
+       xmalloc (strlen (tagfile) + whatlen_max +
+                sizeof "mv..OTAGS;fgrep -v '\t\t' OTAGS >;rm OTAGS");
       for (i = 0; i < current_arg; ++i)
        {
          switch (argbuffer[i].arg_type)
@@ -1342,12 +1358,17 @@ main (int argc, char **argv)
            default:
              continue;         /* the for loop */
            }
-         sprintf (cmd,
-                  "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
-                  tagfile, argbuffer[i].what, tagfile);
+         strcpy (cmd, "mv ");
+         strcat (cmd, tagfile);
+         strcat (cmd, " OTAGS;fgrep -v '\t");
+         strcat (cmd, argbuffer[i].what);
+         strcat (cmd, "\t' OTAGS >");
+         strcat (cmd, tagfile);
+         strcat (cmd, ";rm OTAGS");
          if (system (cmd) != EXIT_SUCCESS)
            fatal ("failed to execute shell command", (char *)NULL);
        }
+      free (cmd);
       append_to_tagfile = TRUE;
     }
 
@@ -1363,11 +1384,14 @@ main (int argc, char **argv)
   if (CTAGS)
     if (append_to_tagfile || update)
       {
-       char cmd[2*BUFSIZ+20];
+       char *cmd = xmalloc (2 * strlen (tagfile) + sizeof "sort -u -o..");
        /* Maybe these should be used:
           setenv ("LC_COLLATE", "C", 1);
           setenv ("LC_ALL", "C", 1); */
-       sprintf (cmd, "sort -u -o %.*s %.*s", BUFSIZ, tagfile, BUFSIZ, tagfile);
+       strcpy (cmd, "sort -u -o ");
+       strcat (cmd, tagfile);
+       strcat (cmd, " ");
+       strcat (cmd, tagfile);
        exit (system (cmd));
       }
   return EXIT_SUCCESS;
@@ -6656,7 +6680,7 @@ linebuffer_setlen (linebuffer *lbp, int toksize)
 
 /* Like malloc but get fatal error if memory is exhausted. */
 static PTR
-xmalloc (unsigned int size)
+xmalloc (size_t size)
 {
   PTR result = (PTR) malloc (size);
   if (result == NULL)
@@ -6665,7 +6689,7 @@ xmalloc (unsigned int size)
 }
 
 static PTR
-xrealloc (char *ptr, unsigned int size)
+xrealloc (char *ptr, size_t size)
 {
   PTR result = (PTR) realloc (ptr, size);
   if (result == NULL)
index d70c655..097bf23 100644 (file)
@@ -325,11 +325,10 @@ main (int argc, char **argv)
          if (desc < 0)
            {
              int mkstemp_errno = errno;
-             char *message = (char *) xmalloc (strlen (tempname) + 50);
-             sprintf (message, "creating %s, which would become the lock file",
-                      tempname);
+             error ("error while creating what would become the lock file",
+                    0, 0);
              errno = mkstemp_errno;
-             pfatal_with_name (message);
+             pfatal_with_name (tempname);
            }
          close (desc);
 
index 2a89379..9fba51a 100644 (file)
@@ -35,6 +35,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <unistd.h>
 #include <errno.h>
+#include <limits.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -128,19 +129,13 @@ lose_syserr (const char *msg)
 static char *
 get_user_id (void)
 {
-  char *name;
   struct passwd *buf = getpwuid (getuid ());
   if (!buf)
     {
-      int count = 1;
-      int uid = (int) getuid ();
-      int tuid = uid;
-      while (tuid /= 10)
-       count++;
-      name = malloc (count+1);
-      if (!name)
-       return NULL;
-      sprintf (name, "%d", uid);
+      long uid = getuid ();
+      char *name = malloc (sizeof uid * CHAR_BIT / 3 + 1);
+      if (name)
+       sprintf (name, "%ld", uid);
       return name;
     }
   return buf->pw_name;
index c1d943c..5e6a6d9 100644 (file)
@@ -1,3 +1,19 @@
+2011-09-04  Michael Albinus  <michael.albinus@gmx.de>
+
+       * net/tramp.el (top): Require 'shell.  Use `tramp-unload-hook' but
+       `tramp-cache-unload-hook' where appropriate.
+       (tramp-methods): Rename `tramp-remote-sh' to
+       `tramp-remote-shell'.  Add `tramp-remote-shell-args'.
+       (tramp-handle-shell-command): New defun, moved from tramp-sh.el.
+
+       * net/tramp-sh.el (top): Don't require 'shell.
+       (tramp-methods): Add `tramp-remote-shell' and
+       `tramp-remote-shell-args' entries.
+       (tramp-sh-file-name-handler-alist): Use `tramp-handle-shell-command'.
+       (tramp-sh-handle-shell-command): Remove.
+       (tramp-find-shell, tramp-open-connection-setup-interactive-shell):
+       Use `tramp-remote-shell'.
+
 2011-09-03  Chong Yidong  <cyd@stupidchicken.com>
 
        * mail/sendmail.el (sendmail-query-once-function): Deleted.
index ceac837..9d71913 100644 (file)
@@ -1,3 +1,17 @@
+2011-09-04  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el (gnus-home-directory): Add warning about setting in .gnus.el
+       (bug#9405).
+
+       * gnus-score.el (gnus-summary-increase-score): Doc clarification
+       (bug#9421).
+
+       * gnus-spec.el (gnus-face-0): Make all the face specs into defcustoms
+       (bug#9425).
+
+       * gnus-art.el (gnus-treatment-function-alist): Remove CRs as the first
+       thing (bug#9426).
+
 2011-09-03  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
        * nnimap.el (nnimap-open-connection-1): Use the correct port number in
index eaf0ed5..9d962fc 100644 (file)
@@ -1657,14 +1657,14 @@ regexp."
 
 (defvar gnus-article-mime-handle-alist-1 nil)
 (defvar gnus-treatment-function-alist
-  '((gnus-treat-x-pgp-sig gnus-article-verify-x-pgp-sig)
+  '((gnus-treat-strip-cr gnus-article-remove-cr)
+    (gnus-treat-x-pgp-sig gnus-article-verify-x-pgp-sig)
     (gnus-treat-strip-banner gnus-article-strip-banner)
     (gnus-treat-strip-headers-in-body gnus-article-strip-headers-in-body)
     (gnus-treat-highlight-signature gnus-article-highlight-signature)
     (gnus-treat-buttonize gnus-article-add-buttons)
     (gnus-treat-fill-article gnus-article-fill-cited-article)
     (gnus-treat-fill-long-lines gnus-article-fill-cited-long-lines)
-    (gnus-treat-strip-cr gnus-article-remove-cr)
     (gnus-treat-unsplit-urls gnus-article-unsplit-urls)
     (gnus-treat-display-x-face gnus-article-display-x-face)
     (gnus-treat-display-face gnus-article-display-face)
index eb7234a..d8e424e 100644 (file)
@@ -522,9 +522,10 @@ of the last successful match.")
 (defun gnus-summary-lower-score (&optional score symp)
   "Make a score entry based on the current article.
 The user will be prompted for header to score on, match type,
-permanence, and the string to be used.  The numerical prefix will be
-used as score.  A symbolic prefix of `a' says to use the `all.SCORE'
-file for the command instead of the current score file."
+permanence, and the string to be used.  The numerical prefix will
+be used as SCORE.  A symbolic prefix of `a' (the SYMP parameter)
+says to use the `all.SCORE' file for the command instead of the
+current score file."
   (interactive (gnus-interactive "P\ny"))
   (gnus-summary-increase-score (- (gnus-score-delta-default score)) symp))
 
@@ -537,9 +538,10 @@ file for the command instead of the current score file."
 (defun gnus-summary-increase-score (&optional score symp)
   "Make a score entry based on the current article.
 The user will be prompted for header to score on, match type,
-permanence, and the string to be used.  The numerical prefix will be
-used as score.  A symbolic prefix of `a' says to use the `all.SCORE'
-file for the command instead of the current score file."
+permanence, and the string to be used.  The numerical prefix will
+be used as SCORE.  A symbolic prefix of `a' (the SYMP parameter)
+says to use the `all.SCORE' file for the command instead of the
+current score file."
   (interactive (gnus-interactive "P\ny"))
   (let* ((nscore (gnus-score-delta-default score))
         (prefix (if (< nscore 0) ?L ?I))
index 0fa64a8..31cb986 100644 (file)
@@ -264,11 +264,30 @@ Return a list of updated types."
       (push (cons 'version emacs-version) gnus-format-specs))
     updated))
 
-(defvar gnus-mouse-face-0 'highlight)
-(defvar gnus-mouse-face-1 'highlight)
-(defvar gnus-mouse-face-2 'highlight)
-(defvar gnus-mouse-face-3 'highlight)
-(defvar gnus-mouse-face-4 'highlight)
+(defcustom gnus-mouse-face-0 'highlight
+  "The \"%(hello%)\" face."
+  :group 'gnus-format
+  :type 'face)
+
+(defcustom gnus-mouse-face-1 'highlight
+  "The \"%1(hello%)\" face."
+  :group 'gnus-format
+  :type 'face)
+
+(defcustom gnus-mouse-face-2 'highlight
+  "The \"%2(hello%)\" face."
+  :group 'gnus-format
+  :type 'face)
+
+(defcustom gnus-mouse-face-3 'highlight
+  "The \"%3(hello%)\" face."
+  :group 'gnus-format
+  :type 'face)
+
+(defcustom gnus-mouse-face-4 'highlight
+  "The \"%4(hello%)\" face."
+  :group 'gnus-format
+  :type 'face)
 
 (defun gnus-mouse-face-function (form type)
   `(gnus-put-text-property
@@ -278,11 +297,30 @@ Return a list of updated types."
         'gnus-mouse-face
        `(quote ,(symbol-value (intern (format "gnus-mouse-face-%d" type)))))))
 
-(defvar gnus-face-0 'bold)
-(defvar gnus-face-1 'italic)
-(defvar gnus-face-2 'bold-italic)
-(defvar gnus-face-3 'bold)
-(defvar gnus-face-4 'bold)
+(defcustom gnus-face-0 'bold
+  "The \"%{hello%}\" face."
+  :group 'gnus-format
+  :type 'face)
+
+(defcustom gnus-face-1 'italic
+  "The \"%1{hello%}\" face."
+  :group 'gnus-format
+  :type 'face)
+
+(defcustom gnus-face-2 'bold-italic
+  "The \"%2{hello%}\" face."
+  :group 'gnus-format
+  :type 'face)
+
+(defcustom gnus-face-3 'bold
+  "The \"%3{hello%}\" face."
+  :group 'gnus-format
+  :type 'face)
+
+(defcustom gnus-face-4 'bold
+  "The \"%4{hello%}\" face."
+  :group 'gnus-format
+  :type 'face)
 
 (defun gnus-face-face-function (form type)
   `(gnus-add-text-properties
index cd9b6ee..34759ce 100644 (file)
@@ -1245,7 +1245,12 @@ REST is a plist of following:
 
 (defcustom gnus-home-directory "~/"
   "Directory variable that specifies the \"home\" directory.
-All other Gnus file and directory variables are initialized from this variable."
+All other Gnus file and directory variables are initialized from this variable.
+
+Note that Gnus is mostly loaded when the `.gnus.el' file is read.
+This means that other directory variables that are initialized
+from this variable won't be set properly if you set this variable
+in `.gnus.el'.  Set this variable in `.emacs' instead."
   :group 'gnus-files
   :type 'directory)
 
index 428bd64..1fa358e 100644 (file)
@@ -28,7 +28,6 @@
 
 (eval-when-compile (require 'cl))      ; ignore-errors
 (require 'tramp)
-(require 'shell)
 
 ;; Pacify byte-compiler.  The function is needed on XEmacs only.  I'm
 ;; not sure at all that this is the right way to do it, but let's hope
@@ -91,7 +90,8 @@ detected as prompt when being sent on echoing hosts, therefore.")
   '("rcp"
     (tramp-login-program        "rsh")
     (tramp-login-args           (("%h") ("-l" "%u")))
-    (tramp-remote-sh            "/bin/sh")
+    (tramp-remote-shell         "/bin/sh")
+    (tramp-remote-shell-args    ("-c"))
     (tramp-copy-program         "rcp")
     (tramp-copy-args            (("-p" "%k") ("-r")))
     (tramp-copy-keep-date       t)
@@ -101,7 +101,8 @@ detected as prompt when being sent on echoing hosts, therefore.")
   '("remcp"
     (tramp-login-program        "remsh")
     (tramp-login-args           (("%h") ("-l" "%u")))
-    (tramp-remote-sh            "/bin/sh")
+    (tramp-remote-shell         "/bin/sh")
+    (tramp-remote-shell-args    ("-c"))
     (tramp-copy-program         "rcp")
     (tramp-copy-args            (("-p" "%k")))
     (tramp-copy-keep-date       t)))
@@ -111,7 +112,8 @@ detected as prompt when being sent on echoing hosts, therefore.")
    (tramp-login-program        "ssh")
    (tramp-login-args           (("-l" "%u") ("-p" "%p")        ("-e" "none") ("%h")))
    (tramp-async-args           (("-q")))
-   (tramp-remote-sh            "/bin/sh")
+   (tramp-remote-shell         "/bin/sh")
+   (tramp-remote-shell-args    ("-c"))
    (tramp-copy-program         "scp")
    (tramp-copy-args            (("-P" "%p") ("-p" "%k")        ("-q") ("-r")))
    (tramp-copy-keep-date       t)
@@ -127,7 +129,8 @@ detected as prompt when being sent on echoing hosts, therefore.")
     (tramp-login-args           (("-l" "%u") ("-p" "%p")
                                 ("-1") ("-e" "none") ("%h")))
     (tramp-async-args           (("-q")))
-    (tramp-remote-sh            "/bin/sh")
+    (tramp-remote-shell         "/bin/sh")
+    (tramp-remote-shell-args    ("-c"))
     (tramp-copy-program         "scp")
     (tramp-copy-args            (("-1") ("-P" "%p") ("-p" "%k") ("-q") ("-r")))
     (tramp-copy-keep-date       t)
@@ -143,7 +146,8 @@ detected as prompt when being sent on echoing hosts, therefore.")
     (tramp-login-args           (("-l" "%u") ("-p" "%p")
                                 ("-2") ("-e" "none") ("%h")))
     (tramp-async-args           (("-q")))
-    (tramp-remote-sh            "/bin/sh")
+    (tramp-remote-shell         "/bin/sh")
+    (tramp-remote-shell-args    ("-c"))
     (tramp-copy-program         "scp")
     (tramp-copy-args            (("-2") ("-P" "%p") ("-p" "%k") ("-q") ("-r")))
     (tramp-copy-keep-date       t)
@@ -161,7 +165,8 @@ detected as prompt when being sent on echoing hosts, therefore.")
                                 ("-o" "ControlMaster=yes")
                                 ("-e" "none") ("%h")))
     (tramp-async-args           (("-q")))
-    (tramp-remote-sh            "/bin/sh")
+    (tramp-remote-shell         "/bin/sh")
+    (tramp-remote-shell-args    ("-c"))
     (tramp-copy-program         "scp")
     (tramp-copy-args            (("-P" "%p") ("-p" "%k") ("-q") ("-r")
                                 ("-o" "ControlPath=%t.%%r@%%h:%%p")
@@ -180,7 +185,8 @@ detected as prompt when being sent on echoing hosts, therefore.")
                                 ("-e" "none") ("-t" "-t")
                                 ("%h") ("/bin/sh")))
     (tramp-async-args           (("-q")))
-    (tramp-remote-sh            "/bin/sh")
+    (tramp-remote-shell         "/bin/sh")
+    (tramp-remote-shell-args    ("-c"))
     (tramp-copy-program         "scp")
     (tramp-copy-args            (("-P" "%p") ("-p" "%k") ("-q") ("-r")))
     (tramp-copy-keep-date       t)
@@ -195,7 +201,8 @@ detected as prompt when being sent on echoing hosts, therefore.")
     (tramp-login-program        "ssh")
     (tramp-login-args           (("-l" "%u") ("-p" "%p") ("-e" "none") ("%h")))
     (tramp-async-args           (("-q")))
-    (tramp-remote-sh            "/bin/sh")
+    (tramp-remote-shell         "/bin/sh")
+    (tramp-remote-shell-args    ("-c"))
     (tramp-copy-program         "sftp")))
 ;;;###tramp-autoload
 (add-to-list 'tramp-methods
@@ -203,7 +210,8 @@ detected as prompt when being sent on echoing hosts, therefore.")
     (tramp-login-program        "ssh")
     (tramp-login-args           (("-l" "%u") ("-p" "%p") ("-e" "none") ("%h")))
     (tramp-async-args           (("-q")))
-    (tramp-remote-sh            "/bin/sh")
+    (tramp-remote-shell         "/bin/sh")
+    (tramp-remote-shell-args    ("-c"))
     (tramp-copy-program         "rsync")
     (tramp-copy-args            (("-e" "ssh") ("-t" "%k") ("-r")))
     (tramp-copy-keep-date       t)
@@ -218,7 +226,8 @@ detected as prompt when being sent on echoing hosts, therefore.")
                                 ("-o" "ControlMaster=yes")
                                 ("-e" "none") ("%h")))
     (tramp-async-args           (("-q")))
-    (tramp-remote-sh            "/bin/sh")
+    (tramp-remote-shell         "/bin/sh")
+    (tramp-remote-shell-args    ("-c"))
     (tramp-copy-program         "rsync")
     (tramp-copy-args            (("-t" "%k") ("-r")))
     (tramp-copy-env             (("RSYNC_RSH")
@@ -234,20 +243,23 @@ detected as prompt when being sent on echoing hosts, therefore.")
   '("rsh"
     (tramp-login-program        "rsh")
     (tramp-login-args           (("%h") ("-l" "%u")))
-    (tramp-remote-sh            "/bin/sh")))
+    (tramp-remote-shell         "/bin/sh")
+    (tramp-remote-shell-args    ("-c"))))
 ;;;###tramp-autoload
 (add-to-list 'tramp-methods
   '("remsh"
     (tramp-login-program        "remsh")
     (tramp-login-args           (("%h") ("-l" "%u")))
-    (tramp-remote-sh            "/bin/sh")))
+    (tramp-remote-shell         "/bin/sh")
+    (tramp-remote-shell-args    ("-c"))))
 ;;;###tramp-autoload
 (add-to-list 'tramp-methods
   '("ssh"
     (tramp-login-program        "ssh")
     (tramp-login-args           (("-l" "%u") ("-p" "%p") ("-e" "none") ("%h")))
     (tramp-async-args           (("-q")))
-    (tramp-remote-sh            "/bin/sh")
+    (tramp-remote-shell         "/bin/sh")
+    (tramp-remote-shell-args    ("-c"))
     (tramp-gw-args              (("-o" "GlobalKnownHostsFile=/dev/null")
                                 ("-o" "UserKnownHostsFile=/dev/null")
                                 ("-o" "StrictHostKeyChecking=no")))
@@ -259,7 +271,8 @@ detected as prompt when being sent on echoing hosts, therefore.")
     (tramp-login-args           (("-l" "%u") ("-p" "%p")
                                 ("-1") ("-e" "none") ("%h")))
     (tramp-async-args           (("-q")))
-    (tramp-remote-sh            "/bin/sh")
+    (tramp-remote-shell         "/bin/sh")
+    (tramp-remote-shell-args    ("-c"))
     (tramp-gw-args              (("-o" "GlobalKnownHostsFile=/dev/null")
                                 ("-o" "UserKnownHostsFile=/dev/null")
                                 ("-o" "StrictHostKeyChecking=no")))
@@ -271,7 +284,8 @@ detected as prompt when being sent on echoing hosts, therefore.")
     (tramp-login-args           (("-l" "%u") ("-p" "%p")
                                 ("-2") ("-e" "none") ("%h")))
     (tramp-async-args           (("-q")))
-    (tramp-remote-sh            "/bin/sh")
+    (tramp-remote-shell         "/bin/sh")
+    (tramp-remote-shell-args    ("-c"))
     (tramp-gw-args              (("-o" "GlobalKnownHostsFile=/dev/null")
                                 ("-o" "UserKnownHostsFile=/dev/null")
                                 ("-o" "StrictHostKeyChecking=no")))
@@ -284,7 +298,8 @@ detected as prompt when being sent on echoing hosts, therefore.")
                                 ("-e" "none") ("-t" "-t")
                                 ("%h") ("/bin/sh")))
     (tramp-async-args           (("-q")))
-    (tramp-remote-sh            "/bin/sh")
+    (tramp-remote-shell         "/bin/sh")
+    (tramp-remote-shell-args    ("-c"))
     (tramp-gw-args              (("-o" "GlobalKnownHostsFile=/dev/null")
                                 ("-o" "UserKnownHostsFile=/dev/null")
                                 ("-o" "StrictHostKeyChecking=no")))
@@ -294,38 +309,44 @@ detected as prompt when being sent on echoing hosts, therefore.")
   '("telnet"
     (tramp-login-program        "telnet")
     (tramp-login-args           (("%h") ("%p")))
-    (tramp-remote-sh            "/bin/sh")
+    (tramp-remote-shell         "/bin/sh")
+    (tramp-remote-shell-args    ("-c"))
     (tramp-default-port         23)))
 ;;;###tramp-autoload
 (add-to-list 'tramp-methods
   '("su"
     (tramp-login-program        "su")
     (tramp-login-args           (("-") ("%u")))
-    (tramp-remote-sh            "/bin/sh")))
+    (tramp-remote-shell         "/bin/sh")
+    (tramp-remote-shell-args    ("-c"))))
 ;;;###tramp-autoload
 (add-to-list 'tramp-methods
   '("sudo"
     (tramp-login-program        "sudo")
     (tramp-login-args           (("-u" "%u") ("-s") ("-H") ("-p" "Password:")))
-    (tramp-remote-sh            "/bin/sh")))
+    (tramp-remote-shell         "/bin/sh")
+    (tramp-remote-shell-args    ("-c"))))
 ;;;###tramp-autoload
 (add-to-list 'tramp-methods
   '("ksu"
     (tramp-login-program        "ksu")
     (tramp-login-args           (("%u") ("-q")))
-    (tramp-remote-sh            "/bin/sh")))
+    (tramp-remote-shell         "/bin/sh")
+    (tramp-remote-shell-args    ("-c"))))
 ;;;###tramp-autoload
 (add-to-list 'tramp-methods
   '("krlogin"
     (tramp-login-program        "krlogin")
     (tramp-login-args           (("%h") ("-l" "%u") ("-x")))
-    (tramp-remote-sh            "/bin/sh")))
+    (tramp-remote-shell         "/bin/sh")
+    (tramp-remote-shell-args    ("-c"))))
 ;;;###tramp-autoload
 (add-to-list 'tramp-methods
   '("plink"
     (tramp-login-program        "plink")
     (tramp-login-args           (("-l" "%u") ("-P" "%p") ("-ssh") ("%h")))
-    (tramp-remote-sh            "/bin/sh")
+    (tramp-remote-shell         "/bin/sh")
+    (tramp-remote-shell-args    ("-c"))
     (tramp-password-end-of-line "xy") ;see docstring for "xy"
     (tramp-default-port         22)))
 ;;;###tramp-autoload
@@ -333,7 +354,8 @@ detected as prompt when being sent on echoing hosts, therefore.")
   '("plink1"
     (tramp-login-program        "plink")
     (tramp-login-args           (("-l" "%u") ("-P" "%p") ("-1" "-ssh") ("%h")))
-    (tramp-remote-sh            "/bin/sh")
+    (tramp-remote-shell         "/bin/sh")
+    (tramp-remote-shell-args    ("-c"))
     (tramp-password-end-of-line "xy") ;see docstring for "xy"
     (tramp-default-port         22)))
 ;;;###tramp-autoload
@@ -348,13 +370,15 @@ detected as prompt when being sent on echoing hosts, therefore.")
                                    tramp-terminal-type
                                    tramp-initial-end-of-output))
                                 ("/bin/sh")))
-    (tramp-remote-sh            "/bin/sh")))
+    (tramp-remote-shell         "/bin/sh")
+    (tramp-remote-shell-args    ("-c"))))
 ;;;###tramp-autoload
 (add-to-list 'tramp-methods
   '("pscp"
     (tramp-login-program        "plink")
     (tramp-login-args           (("-l" "%u") ("-P" "%p") ("-ssh") ("%h")))
-    (tramp-remote-sh            "/bin/sh")
+    (tramp-remote-shell         "/bin/sh")
+    (tramp-remote-shell-args    ("-c"))
     (tramp-copy-program         "pscp")
     (tramp-copy-args            (("-P" "%p") ("-scp") ("-p" "%k")
                                 ("-q") ("-r")))
@@ -367,7 +391,8 @@ detected as prompt when being sent on echoing hosts, therefore.")
   '("psftp"
     (tramp-login-program        "plink")
     (tramp-login-args           (("-l" "%u") ("-P" "%p") ("-ssh") ("%h")))
-    (tramp-remote-sh            "/bin/sh")
+    (tramp-remote-shell         "/bin/sh")
+    (tramp-remote-shell-args    ("-c"))
     (tramp-copy-program         "pscp")
     (tramp-copy-args            (("-P" "%p") ("-sftp") ("-p" "%k")
                                 ("-q") ("-r")))
@@ -379,7 +404,8 @@ detected as prompt when being sent on echoing hosts, therefore.")
   '("fcp"
     (tramp-login-program        "fsh")
     (tramp-login-args           (("%h") ("-l" "%u") ("sh" "-i")))
-    (tramp-remote-sh            "/bin/sh -i")
+    (tramp-remote-shell         "/bin/sh")
+    (tramp-remote-shell-args    ("-i") ("-c"))
     (tramp-copy-program         "fcp")
     (tramp-copy-args            (("-p" "%k")))
     (tramp-copy-keep-date       t)))
@@ -942,7 +968,7 @@ This is used to map a mode number to a permission string.")
     (executable-find . tramp-sh-handle-executable-find)
     (start-file-process . tramp-sh-handle-start-file-process)
     (process-file . tramp-sh-handle-process-file)
-    (shell-command . tramp-sh-handle-shell-command)
+    (shell-command . tramp-handle-shell-command)
     (insert-directory . tramp-sh-handle-insert-directory)
     (expand-file-name . tramp-sh-handle-expand-file-name)
     (substitute-in-file-name . tramp-handle-substitute-in-file-name)
@@ -2853,7 +2879,7 @@ the result will be a local, non-Tramp, filename."
       ;; `process-file-side-effects' has been introduced with GNU
       ;; Emacs 23.2.  If set to `nil', no remote file will be changed
       ;; by `program'.  If it doesn't exist, we assume its default
-      ;; value 't'.
+      ;; value `t'.
       (unless (and (boundp 'process-file-side-effects)
                   (not (symbol-value 'process-file-side-effects)))
         (tramp-flush-directory-property v ""))
@@ -2873,87 +2899,6 @@ the result will be a local, non-Tramp, filename."
        (apply 'call-process program tmpfile buffer display args)
       (delete-file tmpfile))))
 
-(defun tramp-sh-handle-shell-command
-  (command &optional output-buffer error-buffer)
-  "Like `shell-command' for Tramp files."
-  (let* ((asynchronous (string-match "[ \t]*&[ \t]*\\'" command))
-        ;; We cannot use `shell-file-name' and `shell-command-switch',
-        ;; they are variables of the local host.
-        (args (list
-               (tramp-get-method-parameter
-                (tramp-file-name-method
-                 (tramp-dissect-file-name default-directory))
-                'tramp-remote-sh)
-               "-c" (substring command 0 asynchronous)))
-        current-buffer-p
-        (output-buffer
-         (cond
-          ((bufferp output-buffer) output-buffer)
-          ((stringp output-buffer) (get-buffer-create output-buffer))
-          (output-buffer
-           (setq current-buffer-p t)
-           (current-buffer))
-          (t (get-buffer-create
-              (if asynchronous
-                  "*Async Shell Command*"
-                "*Shell Command Output*")))))
-        (error-buffer
-         (cond
-          ((bufferp error-buffer) error-buffer)
-          ((stringp error-buffer) (get-buffer-create error-buffer))))
-        (buffer
-         (if (and (not asynchronous) error-buffer)
-             (with-parsed-tramp-file-name default-directory nil
-               (list output-buffer (tramp-make-tramp-temp-file v)))
-           output-buffer))
-        (p (get-buffer-process output-buffer)))
-
-    ;; Check whether there is another process running.  Tramp does not
-    ;; support 2 (asynchronous) processes in parallel.
-    (when p
-      (if (yes-or-no-p "A command is running.  Kill it? ")
-         (ignore-errors (kill-process p))
-       (error "Shell command in progress")))
-
-    (if current-buffer-p
-       (progn
-         (barf-if-buffer-read-only)
-         (push-mark nil t))
-      (with-current-buffer output-buffer
-       (setq buffer-read-only nil)
-       (erase-buffer)))
-
-    (if (and (not current-buffer-p) (integerp asynchronous))
-       (prog1
-           ;; Run the process.
-           (apply 'start-file-process "*Async Shell*" buffer args)
-         ;; Display output.
-         (pop-to-buffer output-buffer)
-         (setq mode-line-process '(":%s"))
-         (shell-mode))
-
-      (prog1
-         ;; Run the process.
-         (apply 'process-file (car args) nil buffer nil (cdr args))
-       ;; Insert error messages if they were separated.
-       (when (listp buffer)
-         (with-current-buffer error-buffer
-           (insert-file-contents (cadr buffer)))
-         (delete-file (cadr buffer)))
-       (if current-buffer-p
-           ;; This is like exchange-point-and-mark, but doesn't
-           ;; activate the mark.  It is cleaner to avoid activation,
-           ;; even though the command loop would deactivate the mark
-           ;; because we inserted text.
-           (goto-char (prog1 (mark t)
-                        (set-marker (mark-marker) (point)
-                                    (current-buffer))))
-         ;; There's some output, display it.
-         (when (with-current-buffer output-buffer (> (point-max) (point-min)))
-           (if (functionp 'display-message-or-buffer)
-               (tramp-compat-funcall 'display-message-or-buffer output-buffer)
-             (pop-to-buffer output-buffer))))))))
-
 (defun tramp-sh-handle-file-local-copy (filename)
   "Like `file-local-copy' for Tramp files."
   (with-parsed-tramp-file-name filename nil
@@ -3680,7 +3625,7 @@ file exists and nonzero exit status otherwise."
             (tramp-set-connection-property
              vec "remote-shell"
              (tramp-get-method-parameter
-              (tramp-file-name-method vec) 'tramp-remote-sh)))))))))
+              (tramp-file-name-method vec) 'tramp-remote-shell)))))))))
 
 ;; Utility functions.
 
@@ -3716,7 +3661,8 @@ process to set up.  VEC specifies the connection."
     ;; discarded as well.
     (tramp-open-shell
      vec
-     (tramp-get-method-parameter (tramp-file-name-method vec) 'tramp-remote-sh))
+     (tramp-get-method-parameter
+      (tramp-file-name-method vec) 'tramp-remote-shell))
 
     ;; Disable echo.
     (tramp-message vec 5 "Setting up remote shell environment")
index 274bc72..6475ea4 100644 (file)
@@ -58,6 +58,7 @@
 ;;; Code:
 
 (require 'tramp-compat)
+(require 'shell)
 
 ;;; User Customizable Internal Variables:
 
@@ -190,13 +191,16 @@ See the variable `tramp-encoding-shell' for more information."
 This is a list of entries of the form (NAME PARAM1 PARAM2 ...).
 Each NAME stands for a remote access method.  Each PARAM is a
 pair of the form (KEY VALUE).  The following KEYs are defined:
-  * `tramp-remote-sh'
+  * `tramp-remote-shell'
     This specifies the Bourne shell to use on the remote host.  This
     MUST be a Bourne-like shell.  It is normally not necessary to set
     this to any value other than \"/bin/sh\": Tramp wants to use a shell
     which groks tilde expansion, but it can search for it.  Also note
     that \"/bin/sh\" exists on all Unixen, this might not be true for
     the value that you decide to use.  You Have Been Warned.
+  * `tramp-remote-shell-args'
+    For implementation of `shell-command', this specifies the
+    argument to let `tramp-remote-shell' run a command.
   * `tramp-login-program'
     This specifies the name of the program to use for logging in to the
     remote host.  This may be the name of rsh or a workalike program,
@@ -2959,6 +2963,92 @@ User is always nil."
              (delete-file local-copy)))))
       t)))
 
+(defun tramp-handle-shell-command
+  (command &optional output-buffer error-buffer)
+  "Like `shell-command' for Tramp files."
+  (let* ((asynchronous (string-match "[ \t]*&[ \t]*\\'" command))
+        ;; We cannot use `shell-file-name' and `shell-command-switch',
+        ;; they are variables of the local host.
+        (args (append
+               (cons
+                (tramp-get-method-parameter
+                 (tramp-file-name-method
+                  (tramp-dissect-file-name default-directory))
+                 'tramp-remote-shell)
+                (tramp-get-method-parameter
+                 (tramp-file-name-method
+                  (tramp-dissect-file-name default-directory))
+                 'tramp-remote-shell-args))
+               (list (substring command 0 asynchronous))))
+        current-buffer-p
+        (output-buffer
+         (cond
+          ((bufferp output-buffer) output-buffer)
+          ((stringp output-buffer) (get-buffer-create output-buffer))
+          (output-buffer
+           (setq current-buffer-p t)
+           (current-buffer))
+          (t (get-buffer-create
+              (if asynchronous
+                  "*Async Shell Command*"
+                "*Shell Command Output*")))))
+        (error-buffer
+         (cond
+          ((bufferp error-buffer) error-buffer)
+          ((stringp error-buffer) (get-buffer-create error-buffer))))
+        (buffer
+         (if (and (not asynchronous) error-buffer)
+             (with-parsed-tramp-file-name default-directory nil
+               (list output-buffer (tramp-make-tramp-temp-file v)))
+           output-buffer))
+        (p (get-buffer-process output-buffer)))
+
+    ;; Check whether there is another process running.  Tramp does not
+    ;; support 2 (asynchronous) processes in parallel.
+    (when p
+      (if (yes-or-no-p "A command is running.  Kill it? ")
+         (ignore-errors (kill-process p))
+       (error "Shell command in progress")))
+
+    (if current-buffer-p
+       (progn
+         (barf-if-buffer-read-only)
+         (push-mark nil t))
+      (with-current-buffer output-buffer
+       (setq buffer-read-only nil)
+       (erase-buffer)))
+
+    (if (and (not current-buffer-p) (integerp asynchronous))
+       (prog1
+           ;; Run the process.
+           (apply 'start-file-process "*Async Shell*" buffer args)
+         ;; Display output.
+         (pop-to-buffer output-buffer)
+         (setq mode-line-process '(":%s"))
+         (shell-mode))
+
+      (prog1
+         ;; Run the process.
+         (apply 'process-file (car args) nil buffer nil (cdr args))
+       ;; Insert error messages if they were separated.
+       (when (listp buffer)
+         (with-current-buffer error-buffer
+           (insert-file-contents (cadr buffer)))
+         (delete-file (cadr buffer)))
+       (if current-buffer-p
+           ;; This is like exchange-point-and-mark, but doesn't
+           ;; activate the mark.  It is cleaner to avoid activation,
+           ;; even though the command loop would deactivate the mark
+           ;; because we inserted text.
+           (goto-char (prog1 (mark t)
+                        (set-marker (mark-marker) (point)
+                                    (current-buffer))))
+         ;; There's some output, display it.
+         (when (with-current-buffer output-buffer (> (point-max) (point-min)))
+           (if (functionp 'display-message-or-buffer)
+               (tramp-compat-funcall 'display-message-or-buffer output-buffer)
+             (pop-to-buffer output-buffer))))))))
+
 (defun tramp-handle-substitute-in-file-name (filename)
   "Like `substitute-in-file-name' for Tramp files.
 \"//\" and \"/~\" substitute only in the local filename part.
@@ -3477,7 +3567,7 @@ Return the local name of the temporary file."
     (ignore-errors (delete-file tramp-temp-buffer-file-name))))
 
 (add-hook 'kill-buffer-hook 'tramp-delete-temp-file-function)
-(add-hook 'tramp-cache-unload-hook
+(add-hook 'tramp-unload-hook
          (lambda ()
            (remove-hook 'kill-buffer-hook
                         'tramp-delete-temp-file-function)))
index edbd1a1..8c2ca05 100644 (file)
@@ -1,3 +1,7 @@
+2011-09-04  Paul Eggert  <eggert@cs.ucla.edu>
+
+       * config.nt (HAVE_SNPRINTF): New macro.
+
 2011-07-28  Paul Eggert  <eggert@cs.ucla.edu>
 
        Assume freestanding C89 headers, string.h, stdlib.h.
index 3436bc9..ae38075 100644 (file)
@@ -240,6 +240,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #define HAVE_SETSOCKOPT 1
 #define HAVE_GETSOCKNAME 1
 #define HAVE_GETPEERNAME 1
+#define HAVE_SNPRINTF 1
 #define HAVE_LANGINFO_CODESET 1
 /* Local (unix) sockets are not supported.  */
 #undef HAVE_SYS_UN_H
index f395363..e730c79 100644 (file)
@@ -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.
        (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).
index 4828f4e..8dac2a6 100644 (file)
@@ -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.  */
index e96583e..5c28d01 100644 (file)
@@ -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);
 }
 
 
index 79f9f36..638fa4d 100644 (file)
@@ -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);
+    }
+}
index 6759016..580298c 100644 (file)
@@ -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;
        }
index 4cc4762..83ad8d9 100644 (file)
@@ -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);
index e722b53..f2407ce 100644 (file)
@@ -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);
index c28ee78..7235c86 100644 (file)
@@ -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 */
     {
index 5f8d221..34cacb3 100644 (file)
@@ -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))
index c8ae1e7..74a25a1 100644 (file)
@@ -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);
index 711109a..66b857a 100644 (file)
@@ -497,7 +497,7 @@ make_minibuffer_frame (void)
 \f
 /* 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
 
index c39119c..c154797 100644 (file)
@@ -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;
index 313315e..6e602d2 100644 (file)
@@ -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)));
                }
            }
        }
index ab93e0c..51eac36 100644 (file)
@@ -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;
 }
 
index 32b531d..4485080 100644 (file)
@@ -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);
index 9955511..5c84bb8 100644 (file)
@@ -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 */
index d24da72..ec65e88 100644 (file)
@@ -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
index f6cd3a3..4ecf498 100644 (file)
@@ -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;
 
index 32a97e4..7a5d532 100644 (file)
@@ -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);
-
index eb564a1..ad8f3ed 100644 (file)
@@ -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
index 4c9574c..827404a 100644 (file)
@@ -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);
index 35f8986..d67149a 100644 (file)
@@ -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);
index a808832..058ad5f 100644 (file)
@@ -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;
index d892792..b3d67e6 100644 (file)
@@ -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);
index 57fff94..e20bd59 100644 (file)
@@ -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
 \f
 int
 emacs_open (const char *path, int oflag, int mode)
index 837ab39..1041609 100644 (file)
@@ -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
index 96b1144..e385038 100644 (file)
@@ -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);
index 485734e..c6fa5e7 100644 (file)
@@ -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.  */
 
index 1716cc8..f11362c 100644 (file)
@@ -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;
 
index 431ca07..47d55f4 100644 (file)
@@ -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);
     }
 }
 
index 9a3d5fc..194a8f0 100644 (file)
@@ -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;
index c07caec..86393cf 100644 (file)
@@ -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;
 }
index 3086765..fe86a32 100644 (file)
@@ -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);