Code

Change semantics of interpolate to work like snprintf.
authorPierre Habouzit <madcoder@debian.org>
Mon, 10 Sep 2007 10:35:05 +0000 (12:35 +0200)
committerJunio C Hamano <gitster@pobox.com>
Mon, 10 Sep 2007 19:48:33 +0000 (12:48 -0700)
  Also fix many off-by-ones and a useless memset.

Signed-off-by: Pierre Habouzit <madcoder@debian.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
commit.c
interpolate.c

index 99f65cee0e7e30e833f850b5993aa8a5797ba889..25781cc833fb8ce33c3d162c917742e63325f3b0 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -923,15 +923,14 @@ long format_commit_message(const struct commit *commit, const void *format,
 
        do {
                char *buf = *buf_p;
-               unsigned long space = *space_p;
+               unsigned long len;
 
-               space = interpolate(buf, space, format,
+               len = interpolate(buf, *space_p, format,
                                    table, ARRAY_SIZE(table));
-               if (!space)
+               if (len < *space_p)
                        break;
-               buf = xrealloc(buf, space);
+               ALLOC_GROW(buf, len + 1, *space_p);
                *buf_p = buf;
-               *space_p = space;
        } while (1);
        interp_clear_table(table, ARRAY_SIZE(table));
 
index 00826778fc3d760a9b001423cd9c26e7972c126f..3de583238d854675ae872047a2d2b7fb09a66969 100644 (file)
@@ -44,9 +44,8 @@ void interp_clear_table(struct interp *table, int ninterps)
  *        { "%%", "%"},
  *    }
  *
- * Returns 0 on a successful substitution pass that fits in result,
- * Returns a number of bytes needed to hold the full substituted
- * string otherwise.
+ * Returns the length of the substituted string (not including the final \0).
+ * Like with snprintf, if the result is >= reslen, then it overflowed.
  */
 
 unsigned long interpolate(char *result, unsigned long reslen,
@@ -61,8 +60,6 @@ unsigned long interpolate(char *result, unsigned long reslen,
        int i;
        char c;
 
-        memset(result, 0, reslen);
-
        while ((c = *src)) {
                if (c == '%') {
                        /* Try to match an interpolation string. */
@@ -78,9 +75,9 @@ unsigned long interpolate(char *result, unsigned long reslen,
                                value = interps[i].value;
                                valuelen = strlen(value);
 
-                               if (newlen + valuelen + 1 < reslen) {
+                               if (newlen + valuelen < reslen) {
                                        /* Substitute. */
-                                       strncpy(dest, value, valuelen);
+                                       memcpy(dest, value, valuelen);
                                        dest += valuelen;
                                }
                                newlen += valuelen;
@@ -95,8 +92,9 @@ unsigned long interpolate(char *result, unsigned long reslen,
                newlen++;
        }
 
-       if (newlen + 1 < reslen)
-               return 0;
-       else
-               return newlen + 2;
+       /* XXX: the previous loop always keep room for the ending NUL,
+          we just need to check if there was room for a NUL in the first place */
+       if (reslen > 0)
+               *dest = '\0';
+       return newlen;
 }