Merge branch 'ab/i18n-fixup' into maint
[gitweb.git] / strbuf.c
index 9b3c4457f229041784edfa65218aa09de7a5eff8..77444a94df3d4a0cda6403957fd13ea262d3ab24 100644 (file)
--- a/strbuf.c
+++ b/strbuf.c
@@ -63,7 +63,8 @@ void strbuf_attach(struct strbuf *sb, void *buf, size_t len, size_t alloc)
 
 void strbuf_grow(struct strbuf *sb, size_t extra)
 {
-       if (sb->len + extra + 1 <= sb->len)
+       if (unsigned_add_overflows(extra, 1) ||
+           unsigned_add_overflows(sb->len, extra + 1))
                die("you want to use way too much memory");
        if (!sb->alloc)
                sb->buf = NULL;
@@ -152,7 +153,7 @@ int strbuf_cmp(const struct strbuf *a, const struct strbuf *b)
 void strbuf_splice(struct strbuf *sb, size_t pos, size_t len,
                                   const void *data, size_t dlen)
 {
-       if (pos + len < pos)
+       if (unsigned_add_overflows(pos, len))
                die("you want to use way too much memory");
        if (pos > sb->len)
                die("`pos' is too far after the end of the buffer");
@@ -194,24 +195,29 @@ void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len)
 
 void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
 {
-       int len;
        va_list ap;
+       va_start(ap, fmt);
+       strbuf_vaddf(sb, fmt, ap);
+       va_end(ap);
+}
+
+void strbuf_vaddf(struct strbuf *sb, const char *fmt, va_list ap)
+{
+       int len;
+       va_list cp;
 
        if (!strbuf_avail(sb))
                strbuf_grow(sb, 64);
-       va_start(ap, fmt);
-       len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
-       va_end(ap);
+       va_copy(cp, ap);
+       len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, cp);
+       va_end(cp);
        if (len < 0)
-               die("your vsnprintf is broken");
+               die("BUG: your vsnprintf is broken (returned %d)", len);
        if (len > strbuf_avail(sb)) {
                strbuf_grow(sb, len);
-               va_start(ap, fmt);
                len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
-               va_end(ap);
-               if (len > strbuf_avail(sb)) {
-                       die("this should not happen, your snprintf is broken");
-               }
+               if (len > strbuf_avail(sb))
+                       die("BUG: your vsnprintf is broken (insatiable)");
        }
        strbuf_setlen(sb, sb->len + len);
 }