Another harmless size_t warning.
[rsync/rsync.git] / log.c
diff --git a/log.c b/log.c
index 64e97b9..f36b105 100644 (file)
--- a/log.c
+++ b/log.c
@@ -286,10 +286,35 @@ void rprintf(enum logcode code, const char *format, ...)
        int len;
 
        va_start(ap, format);
+       /* Note: might return -1 */
        len = vsnprintf(buf, sizeof(buf), format, ap);
        va_end(ap);
 
-       if (len > sizeof(buf)-1) exit_cleanup(RERR_MESSAGEIO);
+       /* Deal with buffer overruns.  Instead of panicking, just
+        * truncate the resulting string.  Note that some vsnprintf()s
+        * return -1 on truncation, e.g., glibc 2.0.6 and earlier. */
+       if ((size_t) len > sizeof(buf)-1  ||  len < 0) {
+               const char ellipsis[] = "[...]";
+
+               /* Reset length, and zero-terminate the end of our buffer */
+               len = sizeof(buf)-1;
+               buf[len] = '\0';
+
+               /* Copy the ellipsis to the end of the string, but give
+                * us one extra character:
+                *
+                *                  v--- null byte at buf[sizeof(buf)-1]
+                *        abcdefghij0
+                *     -> abcd[...]00  <-- now two null bytes at end
+                *
+                * If the input format string has a trailing newline,
+                * we copy it into that extra null; if it doesn't, well,
+                * all we lose is one byte.  */
+               strncpy(buf+len-sizeof(ellipsis), ellipsis, sizeof(ellipsis));
+               if (format[strlen(format)-1] == '\n') {
+                       buf[len-1] = '\n';
+               }
+       }
 
        rwrite(code, buf, len);
 }
@@ -307,18 +332,21 @@ void rsyserr(enum logcode code, int errcode, const char *format, ...)
 {
        va_list ap;  
        char buf[1024];
-       int len, sys_len;
+       int len;
+       size_t sys_len;
         char *sysmsg;
 
        va_start(ap, format);
+       /* Note: might return <0 */
        len = vsnprintf(buf, sizeof(buf), format, ap);
        va_end(ap);
 
-       if (len > sizeof(buf)-1) exit_cleanup(RERR_MESSAGEIO);
+       if ((size_t) len > sizeof(buf)-1)
+               exit_cleanup(RERR_MESSAGEIO);
 
         sysmsg = strerror(errcode);
         sys_len = strlen(sysmsg);
-        if (len + 3 + sys_len > sizeof(buf) - 1)
+        if ((size_t) len + 3 + sys_len > sizeof(buf) - 1)
                 exit_cleanup(RERR_MESSAGEIO);
 
         strcpy(buf + len, ": ");
@@ -375,7 +403,7 @@ static void log_formatted(enum logcode code,
        char buf[1024];
        char buf2[1024];
        char *p, *s, *n;
-       int l;
+       size_t l;
        extern struct stats stats;              
        extern int am_sender;
        extern int am_daemon;
@@ -442,7 +470,7 @@ static void log_formatted(enum logcode code,
 
                l = strlen(n);
 
-               if ((l-1) + ((int)(s - &buf[0])) > sizeof(buf)) {
+               if (l + ((int)(s - &buf[0])) >= sizeof(buf)) {
                        rprintf(FERROR,"buffer overflow expanding %%%c - exiting\n",
                                p[0]);
                        exit_cleanup(RERR_MESSAGEIO);