diff -up sudo-1.8.6p3/common/lbuf.c.lbufexpandcode sudo-1.8.6p3/common/lbuf.c --- sudo-1.8.6p3/common/lbuf.c.lbufexpandcode 2013-08-12 17:28:52.429562473 +0200 +++ sudo-1.8.6p3/common/lbuf.c 2013-08-12 17:29:21.486668465 +0200 @@ -77,6 +77,17 @@ lbuf_destroy(struct lbuf *lbuf) debug_return; } +static void +lbuf_expand(struct lbuf *lbuf, size_t extra) +{ + if (lbuf->len + extra + 1 >= lbuf->size) { + do { + lbuf->size += 256; + } while (lbuf->len + extra + 1 >= lbuf->size); + lbuf->buf = erealloc(lbuf->buf, lbuf->size); + } +} + /* * Parse the format and append strings, only %s and %% escapes are supported. * Any characters in set are quoted with a backslash. @@ -86,47 +97,40 @@ lbuf_append_quoted(struct lbuf *lbuf, co { va_list ap; int len; - char *cp, *s = NULL; + char *cp, *s; debug_decl(lbuf_append_quoted, SUDO_DEBUG_UTIL) va_start(ap, fmt); while (*fmt != '\0') { - len = 1; if (fmt[0] == '%' && fmt[1] == 's') { - s = va_arg(ap, char *); - len = strlen(s); - } - /* Assume worst case that all chars must be escaped. */ - if (lbuf->len + (len * 2) + 1 >= lbuf->size) { - do { - lbuf->size += 256; - } while (lbuf->len + len + 1 >= lbuf->size); - lbuf->buf = erealloc(lbuf->buf, lbuf->size); - } - if (*fmt == '%') { - if (*(++fmt) == 's') { - while ((cp = strpbrk(s, set)) != NULL) { - len = (int)(cp - s); - memcpy(lbuf->buf + lbuf->len, s, len); - lbuf->len += len; - lbuf->buf[lbuf->len++] = '\\'; - lbuf->buf[lbuf->len++] = *cp; - s = cp + 1; - } - if (*s != '\0') { - len = strlen(s); - memcpy(lbuf->buf + lbuf->len, s, len); - lbuf->len += len; - } - fmt++; - continue; + if ((s = va_arg(ap, char *)) == NULL) + goto done; + while ((cp = strpbrk(s, set)) != NULL) { + len = (int)(cp - s); + lbuf_expand(lbuf, len + 2); + memcpy(lbuf->buf + lbuf->len, s, len); + lbuf->len += len; + lbuf->buf[lbuf->len++] = '\\'; + lbuf->buf[lbuf->len++] = *cp; + s = cp + 1; } + if (*s != '\0') { + len = strlen(s); + lbuf_expand(lbuf, len); + memcpy(lbuf->buf + lbuf->len, s, len); + lbuf->len += len; + } + fmt += 2; + continue; } + lbuf_expand(lbuf, 2); if (strchr(set, *fmt) != NULL) lbuf->buf[lbuf->len++] = '\\'; lbuf->buf[lbuf->len++] = *fmt++; } - lbuf->buf[lbuf->len] = '\0'; +done: + if (lbuf->size != 0) + lbuf->buf[lbuf->len] = '\0'; va_end(ap); debug_return; @@ -140,33 +144,27 @@ lbuf_append(struct lbuf *lbuf, const cha { va_list ap; int len; - char *s = NULL; + char *s; debug_decl(lbuf_append, SUDO_DEBUG_UTIL) va_start(ap, fmt); while (*fmt != '\0') { - len = 1; if (fmt[0] == '%' && fmt[1] == 's') { - s = va_arg(ap, char *); + if ((s = va_arg(ap, char *)) == NULL) + goto done; len = strlen(s); + lbuf_expand(lbuf, len); + memcpy(lbuf->buf + lbuf->len, s, len); + lbuf->len += len; + fmt += 2; + continue; } - if (lbuf->len + len + 1 >= lbuf->size) { - do { - lbuf->size += 256; - } while (lbuf->len + len + 1 >= lbuf->size); - lbuf->buf = erealloc(lbuf->buf, lbuf->size); - } - if (*fmt == '%') { - if (*(++fmt) == 's') { - memcpy(lbuf->buf + lbuf->len, s, len); - lbuf->len += len; - fmt++; - continue; - } - } + lbuf_expand(lbuf, 1); lbuf->buf[lbuf->len++] = *fmt++; } - lbuf->buf[lbuf->len] = '\0'; +done: + if (lbuf->size != 0) + lbuf->buf[lbuf->len] = '\0'; va_end(ap); debug_return;