Change semantics of interpolate to work like snprintf.
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>
This commit is contained in:
parent
f1696ee398
commit
4acfd1b799
9
commit.c
9
commit.c
@ -923,15 +923,14 @@ long format_commit_message(const struct commit *commit, const void *format,
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
char *buf = *buf_p;
|
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));
|
table, ARRAY_SIZE(table));
|
||||||
if (!space)
|
if (len < *space_p)
|
||||||
break;
|
break;
|
||||||
buf = xrealloc(buf, space);
|
ALLOC_GROW(buf, len + 1, *space_p);
|
||||||
*buf_p = buf;
|
*buf_p = buf;
|
||||||
*space_p = space;
|
|
||||||
} while (1);
|
} while (1);
|
||||||
interp_clear_table(table, ARRAY_SIZE(table));
|
interp_clear_table(table, ARRAY_SIZE(table));
|
||||||
|
|
||||||
|
@ -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 the length of the substituted string (not including the final \0).
|
||||||
* Returns a number of bytes needed to hold the full substituted
|
* Like with snprintf, if the result is >= reslen, then it overflowed.
|
||||||
* string otherwise.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
unsigned long interpolate(char *result, unsigned long reslen,
|
unsigned long interpolate(char *result, unsigned long reslen,
|
||||||
@ -61,8 +60,6 @@ unsigned long interpolate(char *result, unsigned long reslen,
|
|||||||
int i;
|
int i;
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
memset(result, 0, reslen);
|
|
||||||
|
|
||||||
while ((c = *src)) {
|
while ((c = *src)) {
|
||||||
if (c == '%') {
|
if (c == '%') {
|
||||||
/* Try to match an interpolation string. */
|
/* Try to match an interpolation string. */
|
||||||
@ -78,9 +75,9 @@ unsigned long interpolate(char *result, unsigned long reslen,
|
|||||||
value = interps[i].value;
|
value = interps[i].value;
|
||||||
valuelen = strlen(value);
|
valuelen = strlen(value);
|
||||||
|
|
||||||
if (newlen + valuelen + 1 < reslen) {
|
if (newlen + valuelen < reslen) {
|
||||||
/* Substitute. */
|
/* Substitute. */
|
||||||
strncpy(dest, value, valuelen);
|
memcpy(dest, value, valuelen);
|
||||||
dest += valuelen;
|
dest += valuelen;
|
||||||
}
|
}
|
||||||
newlen += valuelen;
|
newlen += valuelen;
|
||||||
@ -95,8 +92,9 @@ unsigned long interpolate(char *result, unsigned long reslen,
|
|||||||
newlen++;
|
newlen++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newlen + 1 < reslen)
|
/* XXX: the previous loop always keep room for the ending NUL,
|
||||||
return 0;
|
we just need to check if there was room for a NUL in the first place */
|
||||||
else
|
if (reslen > 0)
|
||||||
return newlen + 2;
|
*dest = '\0';
|
||||||
|
return newlen;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user