sha1_file: guard against invalid loose subdirectory numbers

Loose object subdirectories have hexadecimal names based on the first byte of the hash of contained objects, thus their numerical representation can range from 0 (0x00) to 255 (0xff). Change the type of the corresponding variable in for_each_file_in_obj_subdir() and associated callback functions to unsigned int and add a range check. Suggested-by: Jeff King <peff@peff.net> Signed-off-by: Rene Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

René Scharfe committed Jun 24, 2017 at 16:09 UTC 70c49050d4a16a7e2990e4d3c91d9d12f62e631e
5 files changed +9 -6
builtin/fsck.c
+1 -1
@@ -537,7 +537,7 @@ static int fsck_cruft(const char *basename, const char *path, void *data)
537 return 0;
538 }
539
540 -static int fsck_subdir(int nr, const char *path, void *progress)
540 +static int fsck_subdir(unsigned int nr, const char *path, void *progress)
541 {
542 display_progress(progress, nr + 1);
543 return 0;
builtin/prune-packed.c
+1 -1
@@ -10,7 +10,7 @@ static const char * const prune_packed_usage[] = {
10
11 static struct progress *progress;
12
13 -static int prune_subdir(int nr, const char *path, void *data)
13 +static int prune_subdir(unsigned int nr, const char *path, void *data)
14 {
15 int *opts = data;
16 display_progress(progress, nr + 1);
builtin/prune.c
+1 -1
@@ -68,7 +68,7 @@ static int prune_cruft(const char *basename, const char *path, void *data)
68 return 0;
69 }
70
71 -static int prune_subdir(int nr, const char *path, void *data)
71 +static int prune_subdir(unsigned int nr, const char *path, void *data)
72 {
73 if (!show_only)
74 rmdir(path);
cache.h
+2 -2
@@ -1805,10 +1805,10 @@ typedef int each_loose_object_fn(const struct object_id *oid,
1805 typedef int each_loose_cruft_fn(const char *basename,
1806 const char *path,
1807 void *data);
1808 -typedef int each_loose_subdir_fn(int nr,
1808 +typedef int each_loose_subdir_fn(unsigned int nr,
1809 const char *path,
1810 void *data);
1811 -int for_each_file_in_obj_subdir(int subdir_nr,
1811 +int for_each_file_in_obj_subdir(unsigned int subdir_nr,
1812 struct strbuf *path,
1813 each_loose_object_fn obj_cb,
1814 each_loose_cruft_fn cruft_cb,
sha1_file.c
+4 -1
@@ -3735,7 +3735,7 @@ void assert_sha1_type(const unsigned char *sha1, enum object_type expect)
3735 typename(expect));
3736 }
3737
3738 -int for_each_file_in_obj_subdir(int subdir_nr,
3738 +int for_each_file_in_obj_subdir(unsigned int subdir_nr,
3739 struct strbuf *path,
3740 each_loose_object_fn obj_cb,
3741 each_loose_cruft_fn cruft_cb,
@@ -3747,6 +3747,9 @@ int for_each_file_in_obj_subdir(int subdir_nr,
3747 struct dirent *de;
3748 int r = 0;
3749
3750 + if (subdir_nr > 0xff)
3751 + BUG("invalid loose object subdirectory: %x", subdir_nr);
3752 +
3753 origlen = path->len;
3754 strbuf_complete(path, '/');
3755 strbuf_addf(path, "%02x", subdir_nr);