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

[PATCH/RFC 2/4] skip_prefix: return a non-const pointer

From
Jeff King <peff@peff.net>
Date
Feb 25, 2013, 18:39 UTC
Message-ID
<20130225183948.GB14438@sigill.intra.peff.net>
In-Reply-To
<20130225183009.GB13912@sigill.intra.peff.net>

The const rules in C are such that one cannot write a function that takes a const or non-const pointer and returns a pointer that matches the input in const-ness. Instead, you must take a const pointer (because you are promising not to modify it), and then either return a const pointer (which is safer, but annoying to callers who originally had a non-const pointer) or a non-const pointer (less safe, as you may accidentally drop constness, but less annoying).

This is a well-known problem, and the standard string functions like strchr take the "less annoying" approach. Let's mimic them. Even though this is technically less safe, skip_prefix tends to be used alongside standard string manipulation functions already, so it is not really introducing a new problem.

Signed-off-by: Jeff King <peff@peff.net>
---
I have mixed feelings on this. It _is_ less safe, and this is a known
bug in the C standard. Still, it seems like the more idiomatic C thing
to do.
My main motivation is to avoid a bunch of casts in the next patch.
 builtin/commit.c  | 2 +-
 git-compat-util.h | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/builtin/commit.c b/builtin/commit.c
index 3348aa1..bb6890b 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -895,7 +895,7 @@ static int template_untouched(struct strbuf *sb)
 		return 0;
 
 	stripspace(&tmpl, cleanup_mode == CLEANUP_ALL);
-	start = (char *)skip_prefix(sb->buf, tmpl.buf);
+	start = skip_prefix(sb->buf, tmpl.buf);
 	if (!start)
 		start = sb->buf;
 	strbuf_release(&tmpl);
diff --git a/git-compat-util.h b/git-compat-util.h
index b7eaaa9..56c066b 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -320,10 +320,10 @@ static inline const char *skip_prefix(const char *str, const char *prefix)
 extern int prefixcmp(const char *str, const char *prefix);
 extern int suffixcmp(const char *str, const char *suffix);
 
-static inline const char *skip_prefix(const char *str, const char *prefix)
+static inline char *skip_prefix(const char *str, const char *prefix)
 {
 	size_t len = strlen(prefix);
-	return strncmp(str, prefix, len) ? NULL : str + len;
+	return strncmp(str, prefix, len) ? NULL : (char *)(str + len);
 }
 
 #if defined(NO_MMAP) || defined(USE_WIN32_MMAP)
-- 
1.8.1.4.4.g265d2fa
Previous: Jeff KingNext: Jeff King
Message 10 of 16 in “Crashes while trying to show tag objects with bad timestamps”
  1. Mantas MikulėnasFeb 22, 2013
  2. Jeff KingFeb 22, 2013
  3. Junio C HamanoFeb 22, 2013
  4. Jeff KingFeb 22, 2013
  5. Mantas MikulėnasFeb 22, 2013
  6. Jeff KingFeb 25, 2013
  7. Junio C HamanoFeb 22, 2013
  8. Jeff KingFeb 25, 2013
  9. 1/4 handle malformed dates in ident linesJeff King, Feb 25, 2013
  10. 2/4 skip_prefix: return a non-const pointerJeff King, Feb 25, 2013
  11. 3/4 fsck: check "tagger" linesJeff King, Feb 25, 2013
  12. 4/4 cat-file: print tags raw for "cat-file -p"Jeff King, Feb 25, 2013
  13. Mantas MikulėnasFeb 25, 2013
  14. hash-object doc: "git hash-object -w" can write invalid objectsJonathan Nieder, Feb 22, 2013
  15. Junio C HamanoFeb 22, 2013
  16. Jeff KingFeb 22, 2013

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.