X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=sha1_file.c;h=1efd9ae19a84dbc2765d4011ea06b2145e86ebb3;hb=34a3e695497ab2abbf2fc33a46380accaa8c7c15;hp=3093ac9f5f0d6cfc76f532a2f6690593410e9d6e;hpb=bc8e478a285ff549a3e5182461b064313d400de3;p=git.git diff --git a/sha1_file.c b/sha1_file.c index 3093ac9f5..1efd9ae19 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -33,7 +33,7 @@ const unsigned char null_sha1[20]; static unsigned int sha1_file_open_flag = O_NOATIME; -signed char hexval_table[256] = { +const signed char hexval_table[256] = { -1, -1, -1, -1, -1, -1, -1, -1, /* 00-07 */ -1, -1, -1, -1, -1, -1, -1, -1, /* 08-0f */ -1, -1, -1, -1, -1, -1, -1, -1, /* 10-17 */ @@ -193,7 +193,7 @@ char *sha1_pack_name(const unsigned char *sha1) *buf++ = hex[val >> 4]; *buf++ = hex[val & 0xf]; } - + return base; } @@ -218,7 +218,7 @@ char *sha1_pack_index_name(const unsigned char *sha1) *buf++ = hex[val >> 4]; *buf++ = hex[val & 0xf]; } - + return base; } @@ -352,10 +352,14 @@ static void read_info_alternates(const char * relative_base, int depth) char *map; size_t mapsz; struct stat st; - char path[PATH_MAX]; + const char alt_file_name[] = "info/alternates"; + /* Given that relative_base is no longer than PATH_MAX, + ensure that "path" has enough space to append "/", the + file name, "info/alternates", and a trailing NUL. */ + char path[PATH_MAX + 1 + sizeof alt_file_name]; int fd; - sprintf(path, "%s/info/alternates", relative_base); + sprintf(path, "%s/%s", relative_base, alt_file_name); fd = open(path, O_RDONLY); if (fd < 0) return; @@ -413,7 +417,7 @@ static size_t peak_pack_mapped; static size_t pack_mapped; struct packed_git *packed_git; -void pack_report() +void pack_report(void) { fprintf(stderr, "pack_report: getpagesize() = %10" SZ_FMT "\n" @@ -510,7 +514,10 @@ static int check_packed_git_idx(const char *path, struct packed_git *p) * for offsets larger than 2^31. */ unsigned long min_size = 8 + 4*256 + nr*(20 + 4 + 4) + 20 + 20; - if (idx_size < min_size || idx_size > min_size + (nr - 1)*8) { + unsigned long max_size = min_size; + if (nr) + max_size += (nr - 1)*8; + if (idx_size < min_size || idx_size > max_size) { munmap(idx_map, idx_size); return error("wrong index file size in %s", path); } @@ -833,7 +840,10 @@ void install_packed_git(struct packed_git *pack) static void prepare_packed_git_one(char *objdir, int local) { - char path[PATH_MAX]; + /* Ensure that this buffer is large enough so that we can + append "/pack/" without clobbering the stack even if + strlen(objdir) were PATH_MAX. */ + char path[PATH_MAX + 1 + 4 + 1 + 1]; int len; DIR *dir; struct dirent *de; @@ -855,6 +865,9 @@ static void prepare_packed_git_one(char *objdir, int local) if (!has_extension(de->d_name, ".idx")) continue; + if (len + namelen + 1 > sizeof(path)) + continue; + /* Don't reopen a pack we already have. */ strcpy(path + len, de->d_name); for (p = packed_git; p; p = p->next) { @@ -959,7 +972,7 @@ int check_sha1_signature(const unsigned char *sha1, void *map, unsigned long siz return hashcmp(sha1, real_sha1) ? -1 : 0; } -void *map_sha1_file(const unsigned char *sha1, unsigned long *size) +static void *map_sha1_file(const unsigned char *sha1, unsigned long *size) { struct stat st; void *map; @@ -1139,7 +1152,7 @@ static int parse_sha1_header(const char *hdr, unsigned long *sizep) unsigned long size; /* - * The type can be at most ten bytes (including the + * The type can be at most ten bytes (including the * terminating '\0' that we add), and is followed by * a space. */ @@ -1687,20 +1700,25 @@ static int matches_pack_name(struct packed_git *p, const char *ig) static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e, const char **ignore_packed) { + static struct packed_git *last_found = (void *)1; struct packed_git *p; off_t offset; prepare_packed_git(); + if (!packed_git) + return 0; + p = (last_found == (void *)1) ? packed_git : last_found; - for (p = packed_git; p; p = p->next) { + do { if (ignore_packed) { const char **ig; for (ig = ignore_packed; *ig; ig++) if (!matches_pack_name(p, *ig)) break; if (*ig) - continue; + goto next; } + offset = find_pack_entry_one(sha1, p); if (offset) { /* @@ -1713,18 +1731,27 @@ static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e, cons */ if (p->pack_fd == -1 && open_packed_git(p)) { error("packfile %s cannot be accessed", p->pack_name); - continue; + goto next; } e->offset = offset; e->p = p; hashcpy(e->sha1, sha1); + last_found = p; return 1; } - } + + next: + if (p == last_found) + p = packed_git; + else + p = p->next; + if (p == last_found) + p = p->next; + } while (p); return 0; } -struct packed_git *find_sha1_pack(const unsigned char *sha1, +struct packed_git *find_sha1_pack(const unsigned char *sha1, struct packed_git *packs) { struct packed_git *p;