Skip to content

Commit 7b66bfe

Browse files
authored
Merge pull request libgit2#4575 from pks-t/pks/index-secfixes-master
Index parsing fixes
2 parents 358cc2e + 3db1af1 commit 7b66bfe

File tree

1 file changed

+27
-18
lines changed

1 file changed

+27
-18
lines changed

src/index.c

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2299,8 +2299,9 @@ static size_t index_entry_size(size_t path_len, size_t varint_len, uint32_t flag
22992299
}
23002300
}
23012301

2302-
static size_t read_entry(
2302+
static int read_entry(
23032303
git_index_entry **out,
2304+
size_t *out_size,
23042305
git_index *index,
23052306
const void *buffer,
23062307
size_t buffer_size,
@@ -2314,7 +2315,7 @@ static size_t read_entry(
23142315
char *tmp_path = NULL;
23152316

23162317
if (INDEX_FOOTER_SIZE + minimal_entry_size > buffer_size)
2317-
return 0;
2318+
return -1;
23182319

23192320
/* buffer is not guaranteed to be aligned */
23202321
memcpy(&source, buffer, sizeof(struct entry_short));
@@ -2356,27 +2357,32 @@ static size_t read_entry(
23562357

23572358
path_end = memchr(path_ptr, '\0', buffer_size);
23582359
if (path_end == NULL)
2359-
return 0;
2360+
return -1;
23602361

23612362
path_length = path_end - path_ptr;
23622363
}
23632364

23642365
entry_size = index_entry_size(path_length, 0, entry.flags);
23652366
entry.path = (char *)path_ptr;
23662367
} else {
2367-
size_t varint_len;
2368-
size_t strip_len = git_decode_varint((const unsigned char *)path_ptr,
2369-
&varint_len);
2370-
size_t last_len = strlen(last);
2371-
size_t prefix_len = last_len - strip_len;
2372-
size_t suffix_len = strlen(path_ptr + varint_len);
2373-
size_t path_len;
2374-
2375-
if (varint_len == 0)
2368+
size_t varint_len, last_len, prefix_len, suffix_len, path_len;
2369+
uintmax_t strip_len;
2370+
2371+
strip_len = git_decode_varint((const unsigned char *)path_ptr, &varint_len);
2372+
last_len = strlen(last);
2373+
2374+
if (varint_len == 0 || last_len < strip_len)
23762375
return index_error_invalid("incorrect prefix length");
23772376

2377+
prefix_len = last_len - strip_len;
2378+
suffix_len = strlen(path_ptr + varint_len);
2379+
23782380
GITERR_CHECK_ALLOC_ADD(&path_len, prefix_len, suffix_len);
23792381
GITERR_CHECK_ALLOC_ADD(&path_len, path_len, 1);
2382+
2383+
if (path_len > GIT_PATH_MAX)
2384+
return index_error_invalid("unreasonable path length");
2385+
23802386
tmp_path = git__malloc(path_len);
23812387
GITERR_CHECK_ALLOC(tmp_path);
23822388

@@ -2386,16 +2392,20 @@ static size_t read_entry(
23862392
entry.path = tmp_path;
23872393
}
23882394

2395+
if (entry_size == 0)
2396+
return -1;
2397+
23892398
if (INDEX_FOOTER_SIZE + entry_size > buffer_size)
2390-
return 0;
2399+
return -1;
23912400

23922401
if (index_entry_dup(out, index, &entry) < 0) {
23932402
git__free(tmp_path);
2394-
return 0;
2403+
return -1;
23952404
}
23962405

23972406
git__free(tmp_path);
2398-
return entry_size;
2407+
*out_size = entry_size;
2408+
return 0;
23992409
}
24002410

24012411
static int read_header(struct index_header *dest, const void *buffer)
@@ -2499,10 +2509,9 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
24992509
/* Parse all the entries */
25002510
for (i = 0; i < header.entry_count && buffer_size > INDEX_FOOTER_SIZE; ++i) {
25012511
git_index_entry *entry = NULL;
2502-
size_t entry_size = read_entry(&entry, index, buffer, buffer_size, last);
2512+
size_t entry_size;
25032513

2504-
/* 0 bytes read means an object corruption */
2505-
if (entry_size == 0) {
2514+
if ((error = read_entry(&entry, &entry_size, index, buffer, buffer_size, last)) < 0) {
25062515
error = index_error_invalid("invalid entry");
25072516
goto done;
25082517
}

0 commit comments

Comments
 (0)