X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/8950ac03f8fd0fb645c7d2374195ea884d091f72..59ee743c5f8d131b3e95a206f331c77b923bd5de:/log.c diff --git a/log.c b/log.c index 64e97b91..f36b1052 100644 --- 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);