git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 2/6] Change semantics of interpolate to work like snprintf.

From
Pierre Habouzit <madcoder@debian.org>
Date
Sep 9, 2007, 00:04 UTC
Message-ID
<11892962764194-git-send-email-madcoder@debian.org>
In-Reply-To
<11892962761617-git-send-email-madcoder@debian.org>
  Also fix many off-by-ones and a useless memset.
Signed-off-by: Pierre Habouzit <madcoder@debian.org>
---
 commit.c      |    9 ++++-----
 interpolate.c |   20 ++++++++------------
 2 files changed, 12 insertions(+), 17 deletions(-)
diff --git a/commit.c b/commit.c
index 99f65ce..25781cc 100644
--- 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));
 
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
Previous: Pierre HabouzitNext: Pierre Habouzit
Message 3 of 9 in “Use more strbufs series [on top of next]”
  1. Pierre HabouzitSep 9, 2007
  2. 1/6 Add strbuf_rtrim and strbuf_insert.Pierre Habouzit, Sep 9, 2007
  3. 2/6 Change semantics of interpolate to work like snprintf.Pierre Habouzit, Sep 9, 2007
  4. 3/6 Rework pretty_print_commit to use strbufs instead of custom buffers.Pierre Habouzit, Sep 9, 2007
  5. 4/6 Use strbuf_read in builtin-fetch-tool.c.Pierre Habouzit, Sep 9, 2007
  6. 5/6 Use strbufs to in read_message (imap-send.c), custom buffer--.Pierre Habouzit, Sep 9, 2007
  7. 6/6 Replace all read_fd use with strbuf_read, and get rid of it.Pierre Habouzit, Sep 9, 2007
  8. Pierre HabouzitSep 9, 2007
  9. Linus TorvaldsSep 27, 2007

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.