Skip to content

Commit 6411a0a

Browse files
pks-tgitster
authored andcommitted
builtin/blame: fix type of length variable when emitting object ID
The `length` variable is used to store how many bytes we wish to emit from an object ID. This value will either be the full hash algorithm's length, or the abbreviated hash that can be set via `--abbrev` or the "core.abbrev" option. The former is of type `size_t`, whereas the latter is of type `int`, which causes a warning with "-Wsign-compare". The reason why `abbrev` is using a signed type is mostly that it is initialized with `-1` to indicate that we have to compute the minimum abbreviation length. This length is computed via `find_alignment()`, which always gets called before `emit_other()`, and thus we can assume that the value would never be negative in `emit_other()`. In fact, we can even assume that the value will always be at least `MINIMUM_ABBREV`, which is enforced by both `git_default_core_config()` and `parse_opt_abbrev_cb()`. We implicitly rely on this by subtracting up to 3 without checking for whether the value becomes negative. We then pass the value to printf(3p) to print the prefix of our object's ID, so if that assumption was violated we may end up with undefined behaviour. Squelch the warning by asserting this invariant and casting the value of `abbrev` to `size_t`. This allows us to store the whole length as an unsigned integer, which we can then pass to `fwrite()`. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 87318f2 commit 6411a0a

File tree

1 file changed

+7
-3
lines changed

1 file changed

+7
-3
lines changed

builtin/blame.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
*/
77

88
#define USE_THE_REPOSITORY_VARIABLE
9-
#define DISABLE_SIGN_COMPARE_WARNINGS
109

1110
#include "builtin.h"
1211
#include "config.h"
@@ -468,9 +467,14 @@ static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent, int
468467
reset = GIT_COLOR_RESET;
469468
}
470469

470+
if (abbrev < MINIMUM_ABBREV)
471+
BUG("abbreviation is smaller than minimum length: %d < %d",
472+
abbrev, MINIMUM_ABBREV);
473+
471474
for (cnt = 0; cnt < ent->num_lines; cnt++) {
472475
char ch;
473-
int length = (opt & OUTPUT_LONG_OBJECT_NAME) ? the_hash_algo->hexsz : abbrev;
476+
size_t length = (opt & OUTPUT_LONG_OBJECT_NAME) ?
477+
the_hash_algo->hexsz : (size_t) abbrev;
474478

475479
if (opt & OUTPUT_COLOR_LINE) {
476480
if (cnt > 0) {
@@ -501,7 +505,7 @@ static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent, int
501505
length--;
502506
putchar('?');
503507
}
504-
printf("%.*s", length, hex);
508+
fwrite(hex, 1, length, stdout);
505509
if (opt & OUTPUT_ANNOTATE_COMPAT) {
506510
const char *name;
507511
if (opt & OUTPUT_SHOW_EMAIL)

0 commit comments

Comments
 (0)