@@ -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
24012411static 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