Fix mmap leak caused by reading bad indexes.
If an index is corrupt, or is simply too new for us to understand, we were leaking the mmap that held the entire content of the index. This could be a considerable size on large projects, given that the index is at least 24 bytes * nr_objects. Signed-off-by: Shawn O. Pearce <spearce@spearce.org> Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
parent
30fee0625d
commit
2d88451b7a
23
sha1_file.c
23
sha1_file.c
@ -430,7 +430,8 @@ void pack_report()
|
|||||||
pack_mapped, peak_pack_mapped);
|
pack_mapped, peak_pack_mapped);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int check_packed_git_idx(const char *path, unsigned long *idx_size_,
|
static int check_packed_git_idx(const char *path,
|
||||||
|
unsigned long *idx_size_,
|
||||||
void **idx_map_)
|
void **idx_map_)
|
||||||
{
|
{
|
||||||
void *idx_map;
|
void *idx_map;
|
||||||
@ -446,6 +447,10 @@ static int check_packed_git_idx(const char *path, unsigned long *idx_size_,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
idx_size = st.st_size;
|
idx_size = st.st_size;
|
||||||
|
if (idx_size < 4 * 256 + 20 + 20) {
|
||||||
|
close(fd);
|
||||||
|
return error("index file %s is too small", path);
|
||||||
|
}
|
||||||
idx_map = xmmap(NULL, idx_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
idx_map = xmmap(NULL, idx_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
@ -453,25 +458,25 @@ static int check_packed_git_idx(const char *path, unsigned long *idx_size_,
|
|||||||
*idx_map_ = idx_map;
|
*idx_map_ = idx_map;
|
||||||
*idx_size_ = idx_size;
|
*idx_size_ = idx_size;
|
||||||
|
|
||||||
/* check index map */
|
|
||||||
if (idx_size < 4*256 + 20 + 20)
|
|
||||||
return error("index file %s is too small", path);
|
|
||||||
|
|
||||||
/* a future index format would start with this, as older git
|
/* a future index format would start with this, as older git
|
||||||
* binaries would fail the non-monotonic index check below.
|
* binaries would fail the non-monotonic index check below.
|
||||||
* give a nicer warning to the user if we can.
|
* give a nicer warning to the user if we can.
|
||||||
*/
|
*/
|
||||||
if (index[0] == htonl(PACK_IDX_SIGNATURE))
|
if (index[0] == htonl(PACK_IDX_SIGNATURE)) {
|
||||||
|
munmap(idx_map, idx_size);
|
||||||
return error("index file %s is a newer version"
|
return error("index file %s is a newer version"
|
||||||
" and is not supported by this binary"
|
" and is not supported by this binary"
|
||||||
" (try upgrading GIT to a newer version)",
|
" (try upgrading GIT to a newer version)",
|
||||||
path);
|
path);
|
||||||
|
}
|
||||||
|
|
||||||
nr = 0;
|
nr = 0;
|
||||||
for (i = 0; i < 256; i++) {
|
for (i = 0; i < 256; i++) {
|
||||||
unsigned int n = ntohl(index[i]);
|
unsigned int n = ntohl(index[i]);
|
||||||
if (n < nr)
|
if (n < nr) {
|
||||||
|
munmap(idx_map, idx_size);
|
||||||
return error("non-monotonic index %s", path);
|
return error("non-monotonic index %s", path);
|
||||||
|
}
|
||||||
nr = n;
|
nr = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -482,8 +487,10 @@ static int check_packed_git_idx(const char *path, unsigned long *idx_size_,
|
|||||||
* - 20-byte SHA1 of the packfile
|
* - 20-byte SHA1 of the packfile
|
||||||
* - 20-byte SHA1 file checksum
|
* - 20-byte SHA1 file checksum
|
||||||
*/
|
*/
|
||||||
if (idx_size != 4*256 + nr * 24 + 20 + 20)
|
if (idx_size != 4*256 + nr * 24 + 20 + 20) {
|
||||||
|
munmap(idx_map, idx_size);
|
||||||
return error("wrong index file size in %s", path);
|
return error("wrong index file size in %s", path);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user