Skip to content

Commit

Permalink
Change semantics of interpolate to work like snprintf.
Browse files Browse the repository at this point in the history
  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>
  • Loading branch information
Pierre Habouzit authored and Junio C Hamano committed Sep 10, 2007
1 parent f1696ee commit 4acfd1b
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 16 deletions.
9 changes: 4 additions & 5 deletions commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand Down
20 changes: 9 additions & 11 deletions interpolate.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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. */
Expand All @@ -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;
Expand All @@ -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;
}

0 comments on commit 4acfd1b

Please sign in to comment.