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

[PATCH 06/10] global: fix unsigned integer promotions in ternary statements

From
Patrick Steinhardt <ps@pks.im>
Date
Nov 29, 2024, 13:13 UTC
Message-ID
<20241129-pks-sign-compare-v1-6-fc406b984bc9@pks.im>
In-Reply-To
<20241129-pks-sign-compare-v1-0-fc406b984bc9@pks.im>

We have several cases in our codebase where the ternary operator changes signedness from a signed integer type to an unsigned one. This causes warnings with `-Wsign-compare`. Generally, we seem to have three classes of this in our codebase:

  - Cases where we know that the result is well-formed, e.g. when
    indexing into strings to determine the length of substrings.
  - Cases where we want `-1` to mean "unlimited", counting on the
    wrap-around.
  - Cases where we may indeed run into problems when one of the
    statements returns a value that is too big.

Out of these only the last class is a bit worrying, but we can address it by adding a call to `cast_size_t_to_int()`. Like this we're better protected in case we have unexpectedly huge input as we'd die instead of silently doing the wrong thing.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 builtin/blame.c           | 3 ++-
 builtin/patch-id.c        | 2 +-
 dir.c                     | 4 ++--
 gettext.c                 | 4 +---
 gpg-interface.c           | 2 +-
 scalar.c                  | 2 +-
 strbuf.c                  | 2 +-
 t/helper/test-csprng.c    | 4 +---
 t/helper/test-genrandom.c | 4 +---
 9 files changed, 11 insertions(+), 16 deletions(-)
diff --git a/builtin/blame.c b/builtin/blame.c
index f0d209791e44025b1965cd447cf4fc1e2ca5f009..6c6b0c7ef1a4d992064c7664bbf1229ef0286b97 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -470,7 +470,8 @@ static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent, int
 
 	for (cnt = 0; cnt < ent->num_lines; cnt++) {
 		char ch;
-		int length = (opt & OUTPUT_LONG_OBJECT_NAME) ? the_hash_algo->hexsz : abbrev;
+		int length = (opt & OUTPUT_LONG_OBJECT_NAME) ?
+			cast_size_t_to_int(the_hash_algo->hexsz) : abbrev;
 
 		if (opt & OUTPUT_COLOR_LINE) {
 			if (cnt > 0) {
diff --git a/builtin/patch-id.c b/builtin/patch-id.c
index 56585757477911c96bbb9ef2cf3710691b8e744e..87fa586c4d552ba61cd2ac2cf079d68241eb3275 100644
--- a/builtin/patch-id.c
+++ b/builtin/patch-id.c
@@ -163,7 +163,7 @@ static int get_one_patchid(struct object_id *next_oid, struct object_id *result,
 			after--;
 
 		/* Add line to hash algo (possibly removing whitespace) */
-		len = verbatim ? strlen(line) : remove_space(line);
+		len = verbatim ? cast_size_t_to_int(strlen(line)) : remove_space(line);
 		patchlen += len;
 		the_hash_algo->update_fn(&ctx, line, len);
 	}
diff --git a/dir.c b/dir.c
index 5b2181e5899ce951791aa5e46ccdbb2d71ce6144..fc77ffe56c9d8353d918553223f5521fa3bc3a94 100644
--- a/dir.c
+++ b/dir.c
@@ -1643,7 +1643,7 @@ static void prep_exclude(struct dir_struct *dir,
 		strbuf_init(&dir->internal.basebuf, PATH_MAX);
 
 	/* Read from the parent directories and push them down. */
-	current = stk ? stk->baselen : -1;
+	current = stk ? cast_size_t_to_int(stk->baselen) : -1;
 	strbuf_setlen(&dir->internal.basebuf, current < 0 ? 0 : current);
 	if (dir->untracked)
 		untracked = stk ? stk->ucd : dir->untracked->root;
@@ -2896,7 +2896,7 @@ static void new_untracked_cache(struct index_state *istate, int flags)
 	struct untracked_cache *uc = xcalloc(1, sizeof(*uc));
 	strbuf_init(&uc->ident, 100);
 	uc->exclude_per_dir = ".gitignore";
-	uc->dir_flags = flags >= 0 ? flags : new_untracked_cache_flags(istate);
+	uc->dir_flags = flags >= 0 ? (unsigned) flags : new_untracked_cache_flags(istate);
 	set_untracked_ident(uc);
 	istate->untracked = uc;
 	istate->cache_changed |= UNTRACKED_CHANGED;
diff --git a/gettext.c b/gettext.c
index 8d08a61f8487dc30559e5e5d6d31cf06a92789e1..ecb0c70c1144ce8b4280b78a2b443138e8af6603 100644
--- a/gettext.c
+++ b/gettext.c
@@ -2,8 +2,6 @@
  * Copyright (c) 2010 Ævar Arnfjörð Bjarmason
  */
 
-#define DISABLE_SIGN_COMPARE_WARNINGS
-
 #include "git-compat-util.h"
 #include "abspath.h"
 #include "environment.h"
@@ -135,7 +133,7 @@ int gettext_width(const char *s)
 	if (is_utf8 == -1)
 		is_utf8 = is_utf8_locale();
 
-	return is_utf8 ? utf8_strwidth(s) : strlen(s);
+	return is_utf8 ? utf8_strwidth(s) : cast_size_t_to_int(strlen(s));
 }
 #endif
 
diff --git a/gpg-interface.c b/gpg-interface.c
index a67d80475bf9d8452de0c3ae9bb08ceeb4c11c4b..e1720361f17e8b3b3315f0a5d93a827e11b2b036 100644
--- a/gpg-interface.c
+++ b/gpg-interface.c
@@ -700,7 +700,7 @@ size_t parse_signed_buffer(const char *buf, size_t size)
 			match = len;
 
 		eol = memchr(buf + len, '\n', size - len);
-		len += eol ? eol - (buf + len) + 1 : size - len;
+		len += eol ? (size_t) (eol - (buf + len) + 1) : size - len;
 	}
 	return match;
 }
diff --git a/scalar.c b/scalar.c
index 87bb30991bf768534a988608d9b194dc8b5ba78a..ce18fab07c08be715142379fd9d757e96c554fbb 100644
--- a/scalar.c
+++ b/scalar.c
@@ -380,7 +380,7 @@ static int delete_enlistment(struct strbuf *enlistment)
 	offset = offset_1st_component(enlistment->buf);
 	path_sep = find_last_dir_sep(enlistment->buf + offset);
 	strbuf_add(&parent, enlistment->buf,
-		   path_sep ? path_sep - enlistment->buf : offset);
+		   path_sep ? (size_t) (path_sep - enlistment->buf) : offset);
 	if (chdir(parent.buf) < 0) {
 		int res = error_errno(_("could not switch to '%s'"), parent.buf);
 		strbuf_release(&parent);
diff --git a/strbuf.c b/strbuf.c
index 8ddd4b06c595ac3f8b38a65d3e1ca4b340fddf9f..8c027a67942a72b9078c7f6e144c883c76d461d4 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -1055,7 +1055,7 @@ void strbuf_stripspace(struct strbuf *sb, const char *comment_prefix)
 
 	for (i = j = 0; i < sb->len; i += len, j += newlen) {
 		eol = memchr(sb->buf + i, '\n', sb->len - i);
-		len = eol ? eol - (sb->buf + i) + 1 : sb->len - i;
+		len = eol ? (size_t) (eol - (sb->buf + i) + 1) : sb->len - i;
 
 		if (comment_prefix && len &&
 		    starts_with(sb->buf + i, comment_prefix)) {
diff --git a/t/helper/test-csprng.c b/t/helper/test-csprng.c
index ea9b9b656307d32bdc1f2e15a91793b1dda9c463..31dbe7db4ac61639541f15d262cea64368fec78f 100644
--- a/t/helper/test-csprng.c
+++ b/t/helper/test-csprng.c
@@ -1,5 +1,3 @@
-#define DISABLE_SIGN_COMPARE_WARNINGS
-
 #include "test-tool.h"
 #include "git-compat-util.h"
 
@@ -14,7 +12,7 @@ int cmd__csprng(int argc, const char **argv)
 		return 2;
 	}
 
-	count = (argc == 2) ? strtoul(argv[1], NULL, 0) : -1L;
+	count = (argc == 2) ? strtoul(argv[1], NULL, 0) : (unsigned long) -1L;
 
 	while (count) {
 		unsigned long chunk = count < sizeof(buf) ? count : sizeof(buf);
diff --git a/t/helper/test-genrandom.c b/t/helper/test-genrandom.c
index 5b51e6648d8e698b09f400efcf67a0708c226e9d..efca20e7efff46bf66c2b8888ce88db02e545cd5 100644
--- a/t/helper/test-genrandom.c
+++ b/t/helper/test-genrandom.c
@@ -4,8 +4,6 @@
  * Copyright (C) 2007 by Nicolas Pitre, licensed under the GPL version 2.
  */
 
-#define DISABLE_SIGN_COMPARE_WARNINGS
-
 #include "test-tool.h"
 #include "git-compat-util.h"
 
@@ -24,7 +22,7 @@ int cmd__genrandom(int argc, const char **argv)
 		next = next * 11 + *c;
 	} while (*c++);
 
-	count = (argc == 3) ? strtoul(argv[2], NULL, 0) : -1L;
+	count = (argc == 3) ? strtoul(argv[2], NULL, 0) : (unsigned long) -1L;
 
 	while (count--) {
 		next = next * 1103515245 + 12345;
-- 
2.47.0.366.g5daf58cba8.dirty
Previous: Patrick SteinhardtNext: shejialuo
Message 6 of 66 in “Start compiling with `-Wsign-compare`”
  1. 00/10 Start compiling with `-Wsign-compare`Patrick Steinhardt, Nov 29, 2024
  2. 02/10 compat/regex: explicitly ignore "-Wsign-compare" warningsPatrick Steinhardt, Nov 29, 2024
  3. 01/10 git-compat-util: introduce macros to disable "-Wsign-compare" warningsPatrick Steinhardt, Nov 29, 2024
  4. 03/10 compat/win32: fix -Wsign-compare warning in "wWinMain()"Patrick Steinhardt, Nov 29, 2024
  5. 05/10 config.mak.dev: drop `-Wno-sign-compare`Patrick Steinhardt, Nov 29, 2024
  6. 06/10 global: fix unsigned integer promotions in ternary statementsPatrick Steinhardt, Nov 29, 2024
  7. shejialuoNov 30, 2024
  8. Patrick SteinhardtDec 2, 2024
  9. Jeff KingDec 1, 2024
  10. Patrick SteinhardtDec 2, 2024
  11. 04/10 global: mark code units that generate warnings with `-Wsign-compare`Patrick Steinhardt, Nov 29, 2024
  12. 07/10 diff.h: fix index used to loop through unsigned integerPatrick Steinhardt, Nov 29, 2024
  13. 09/10 daemon: fix loops that have mismatching integer typesPatrick Steinhardt, Nov 29, 2024
  14. Jeff KingDec 1, 2024
  15. Patrick SteinhardtDec 2, 2024
  16. Jeff KingDec 5, 2024
  17. 08/10 global: trivial conversions to fix `-Wsign-compare` warningsPatrick Steinhardt, Nov 29, 2024
  18. Jeff KingDec 1, 2024
  19. Patrick SteinhardtDec 2, 2024
  20. 10/10 daemon: fix type of `max_connections`Patrick Steinhardt, Nov 29, 2024
  21. Jeff KingDec 1, 2024
  22. shejialuoNov 30, 2024
  23. Patrick SteinhardtDec 2, 2024
  24. Jeff KingDec 1, 2024
  25. Patrick SteinhardtDec 2, 2024
  26. 00/15 Start compiling with `-Wsign-compare`Patrick Steinhardt, Dec 5, 2024
  27. 01/15 git-compat-util: introduce macros to disable "-Wsign-compare" warningsPatrick Steinhardt, Dec 5, 2024
  28. 02/15 compat/regex: explicitly ignore "-Wsign-compare" warningsPatrick Steinhardt, Dec 5, 2024
  29. 03/15 compat/win32: fix -Wsign-compare warning in "wWinMain()"Patrick Steinhardt, Dec 5, 2024
  30. 05/15 config.mak.dev: drop `-Wno-sign-compare`Patrick Steinhardt, Dec 5, 2024
  31. 04/15 global: mark code units that generate warnings with `-Wsign-compare`Patrick Steinhardt, Dec 5, 2024
  32. 06/15 diff.h: fix index used to loop through unsigned integerPatrick Steinhardt, Dec 5, 2024
  33. 07/15 sign-compare: 32-bit supportPatrick Steinhardt, Dec 5, 2024
  34. Jeff KingDec 5, 2024
  35. Patrick SteinhardtDec 6, 2024
  36. 08/15 global: trivial conversions to fix `-Wsign-compare` warningsPatrick Steinhardt, Dec 5, 2024
  37. 09/15 daemon: fix loops that have mismatching integer typesPatrick Steinhardt, Dec 5, 2024
  38. 11/15 gpg-interface: address -Wsign-comparison warningsPatrick Steinhardt, Dec 5, 2024
  39. 10/15 daemon: fix type of `max_connections`Patrick Steinhardt, Dec 5, 2024
  40. 12/15 builtin/blame: fix type of `length` variable when emitting object IDPatrick Steinhardt, Dec 5, 2024
  41. 13/15 builtin/patch-id: fix type of `get_one_patchid()`Patrick Steinhardt, Dec 5, 2024
  42. 14/15 scalar: address -Wsign-compare warningsPatrick Steinhardt, Dec 5, 2024
  43. 15/15 t/helper: don't depend on implicit wraparoundPatrick Steinhardt, Dec 5, 2024
  44. 00/16 Start compiling with `-Wsign-compare`Patrick Steinhardt, Dec 6, 2024
  45. 01/16 git-compat-util: introduce macros to disable "-Wsign-compare" warningsPatrick Steinhardt, Dec 6, 2024
  46. karthik nayakDec 6, 2024
  47. 02/16 compat/regex: explicitly ignore "-Wsign-compare" warningsPatrick Steinhardt, Dec 6, 2024
  48. 03/16 compat/win32: fix -Wsign-compare warning in "wWinMain()"Patrick Steinhardt, Dec 6, 2024
  49. 05/16 config.mak.dev: drop `-Wno-sign-compare`Patrick Steinhardt, Dec 6, 2024
  50. 04/16 global: mark code units that generate warnings with `-Wsign-compare`Patrick Steinhardt, Dec 6, 2024
  51. 06/16 diff.h: fix index used to loop through unsigned integerPatrick Steinhardt, Dec 6, 2024
  52. 07/16 csum-file: fix -Wsign-compare warning on 32-bit platformPatrick Steinhardt, Dec 6, 2024
  53. 08/16 pkt-line: fix -Wsign-compare warning on 32 bit platformPatrick Steinhardt, Dec 6, 2024
  54. Jeff KingDec 8, 2024
  55. Junio C HamanoDec 9, 2024
  56. 09/16 global: trivial conversions to fix `-Wsign-compare` warningsPatrick Steinhardt, Dec 6, 2024
  57. 10/16 daemon: fix loops that have mismatching integer typesPatrick Steinhardt, Dec 6, 2024
  58. 11/16 daemon: fix type of `max_connections`Patrick Steinhardt, Dec 6, 2024
  59. 12/16 gpg-interface: address -Wsign-comparison warningsPatrick Steinhardt, Dec 6, 2024
  60. 13/16 builtin/blame: fix type of `length` variable when emitting object IDPatrick Steinhardt, Dec 6, 2024
  61. Johannes SchindelinJan 8, 2025
  62. Patrick SteinhardtJan 9, 2025
  63. 14/16 builtin/patch-id: fix type of `get_one_patchid()`Patrick Steinhardt, Dec 6, 2024
  64. 15/16 scalar: address -Wsign-compare warningsPatrick Steinhardt, Dec 6, 2024
  65. 16/16 t/helper: don't depend on implicit wraparoundPatrick Steinhardt, Dec 6, 2024
  66. karthik nayakDec 6, 2024

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.