[PATCH 2/3] Change semantics of interpolate to work like snprintf.
From: Pierre Habouzit <hidden>
Date: 2016-06-15 22:43:34
Subsystem:
the rest · Maintainer:
Linus Torvalds
Also fix many off-by-ones and a useless memset. Signed-off-by: Pierre Habouzit <redacted> --- commit.c | 9 ++++----- interpolate.c | 20 ++++++++------------ 2 files changed, 12 insertions(+), 17 deletions(-)
diff --git a/commit.c b/commit.c
index dc5a064..30db9f4 100644
--- a/commit.c
+++ b/commit.c@@ -922,15 +922,14 @@ static long format_commit_message(const struct commit *commit, do { char *buf = *buf_p; - unsigned long space = *space_p; + unsigned long len; - space = interpolate(buf, space, user_format, + len = interpolate(buf, *space_p, user_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));
diff --git a/interpolate.c b/interpolate.c
index 0082677..ff4fb10 100644
--- a/interpolate.c
+++ b/interpolate.c@@ -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;
@@ -89,14 +86,13 @@ unsigned long interpolate(char *result, unsigned long reslen, } } /* Straight copy one non-interpolation character. */ - if (newlen + 1 < reslen) + if (newlen < reslen) *dest++ = *src; src++; newlen++; } - if (newlen + 1 < reslen) - return 0; - else - return newlen + 2; + if (reslen > 0) + *dest = '\0'; + return newlen; }
--
1.5.3.1