Don't use MB_CUR_MAX if compiling without multibyte support.
authorPeter Maydell <pmaydell@chiark.greenend.org.uk>
Thu, 22 May 2008 10:42:09 +0000 (10:42 +0000)
committerPeter Maydell <pmaydell@chiark.greenend.org.uk>
Thu, 22 May 2008 10:42:09 +0000 (10:42 +0000)
Don't rely on return value of sprintf(). (Ported from trunk.)

ChangeLog
uip/scansbr.c
uip/whatnowsbr.c

index 507c457..12f2f12 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2008-05-22  Peter Maydell  <pmaydell@chiark.greenend.org.uk>
+
+       * uip/scansbr.c: don't use MB_CUR_MAX if we aren't compiled
+       with multibyte support. (Ported from trunk.)
+
+       * uip/whatnowsbr.c: factor out common code for writing ls
+       shell command, and make it do more sensible buffer length
+       checks. Also avoid relying on the return value of sprintf(),
+       as some old systems don't return number of characters written.
+       (Ported from trunk.)
+
 2008-05-21  Peter Maydell  <pmaydell@chiark.greenend.org.uk>
 
        * sbr/utils.c (mh_xrealloc): don't assume realloc() can
index 1b6a0ed..6a9278b 100644 (file)
@@ -68,6 +68,11 @@ char *scanl = 0;                     /* text of most recent scanline    */
 int sc_width (void);                   /* from termsbr.c */
 static int mh_fputs(char *, FILE *);
 
+#ifdef MULTIBYTE_SUPPORT
+#define SCAN_CHARWIDTH MB_CUR_MAX
+#else
+#define SCAN_CHARWIDTH 1
+#endif
 
 int
 scan (FILE *inb, int innum, int outnum, char *nfs, int width, int curflg,
@@ -98,7 +103,7 @@ scan (FILE *inb, int innum, int outnum, char *nfs, int width, int curflg,
                width = MAXSCANL;
        }
        dat[3] = slwidth = width;
-       scanl = (char *) mh_xmalloc((size_t) MB_CUR_MAX * (slwidth + 2) );
+       scanl = (char *) mh_xmalloc((size_t) SCAN_CHARWIDTH * (slwidth + 2) );
        if (outnum)
            umask(~m_gmprot());
 
index 0a959db..72e9d1f 100644 (file)
@@ -120,6 +120,7 @@ static int buildfile (char **, char *);
 static int check_draft (char *);
 static int whomfile (char **, char *);
 static int removefile (char *);
+static void writelscmd(char *, int, char *, char **);
 
 #ifdef HAVE_LSTAT
 static int copyf (char *, char *);
@@ -353,17 +354,7 @@ WhatNow (int argc, char **argv)
             *  Use the user's shell so that we can take advantage of any
             *  syntax that the user is accustomed to.
             */
-
-           cp = buf + sprintf(buf, "$SHELL -c \" cd %s;ls", cwd);
-
-           while (*++argp != (char *)0) {
-               if (cp + strlen(*argp) + 2 >= buf + BUFSIZ)
-                   adios((char *)0, "arguments too long");
-
-               cp += sprintf(cp, " %s", *argp);
-           }
-
-           (void)strcat(cp, "\"");
+           writelscmd(buf, sizeof(buf), cwd, argp);
            (void)system(buf);
            break;
 
@@ -423,17 +414,7 @@ WhatNow (int argc, char **argv)
             *  Build a command line that causes the user's shell to list the file name
             *  arguments.  This handles and wildcard expansion, tilde expansion, etc.
             */
-
-           cp = buf + sprintf(buf, "$SHELL -c \" cd %s;ls", cwd);
-
-           while (*++argp != (char *)0) {
-               if (cp + strlen(*argp) + 3 >= buf + BUFSIZ)
-                   adios((char *)0, "arguments too long");
-
-               cp += sprintf(cp, " %s", *argp);
-           }
-
-           (void)strcat(cp, "\"");
+           writelscmd(buf, sizeof(buf), cwd, argp);
 
            /*
             *  Read back the response from the shell, which contains a number of lines
@@ -560,6 +541,40 @@ WhatNow (int argc, char **argv)
     /*NOTREACHED*/
 }
 
+
+/*
+ * Build a command line that causes the user's shell to list the file name
+ * arguments.  This handles and wildcard expansion, tilde expansion, etc.
+ */
+static void
+writelscmd(char *buf, int bufsz, char *cwd, char **argp)
+{
+    char *cp;
+    int ln = snprintf(buf, bufsz, "$SHELL -c \" cd %s;ls", cwd);
+    /* NB that some snprintf() return -1 on overflow rather than the
+     * new C99 mandated 'number of chars that would have been written'
+     */
+    /* length checks here and inside the loop allow for the
+     * trailing " and NUL
+     */
+    if (ln < 0 || ln + 2 > bufsz)
+       adios((char *)0, "arguments too long");
+    
+    cp = buf + ln;
+    
+    while (*++argp != (char *)0) {
+       ln = strlen(*argp);
+       /* +3 for leading space and trailing quote and NUL */
+       if (ln + 3 > bufsz - (cp-buf))
+           adios((char *)0, "arguments too long");
+       *cp++ = ' ';
+       memcpy(cp, *argp, ln+1);
+       cp += ln;
+    }
+    *cp++ = '"';
+    *cp = 0;
+}
+
 /*
  * EDIT
  */