| 3544 | #define EOIE_SIZE_WITH_HEADER (4 + 4 + EOIE_SIZE) /* <4-byte signature> + <4-byte length> + EOIE_SIZE */ |
| 3545 | |
| 3546 | static size_t read_eoie_extension(const char *mmap, size_t mmap_size) |
| 3547 | { |
| 3548 | /* |
| 3549 | * The end of index entries (EOIE) extension is guaranteed to be last |
| 3550 | * so that it can be found by scanning backwards from the EOF. |
| 3551 | * |
| 3552 | * "EOIE" |
| 3553 | * <4-byte length> |
| 3554 | * <4-byte offset> |
| 3555 | * <20-byte hash> |
| 3556 | */ |
| 3557 | const char *index, *eoie; |
| 3558 | uint32_t extsize; |
| 3559 | size_t offset, src_offset; |
| 3560 | unsigned char hash[GIT_MAX_RAWSZ]; |
| 3561 | struct git_hash_ctx c; |
| 3562 | |
| 3563 | /* ensure we have an index big enough to contain an EOIE extension */ |
| 3564 | if (mmap_size < sizeof(struct cache_header) + EOIE_SIZE_WITH_HEADER + the_hash_algo->rawsz) |
| 3565 | return 0; |
| 3566 | |
| 3567 | /* validate the extension signature */ |
| 3568 | index = eoie = mmap + mmap_size - EOIE_SIZE_WITH_HEADER - the_hash_algo->rawsz; |
| 3569 | if (CACHE_EXT(index) != CACHE_EXT_ENDOFINDEXENTRIES) |
| 3570 | return 0; |
| 3571 | index += sizeof(uint32_t); |
| 3572 | |
| 3573 | /* validate the extension size */ |
| 3574 | extsize = get_be32(index); |
| 3575 | if (extsize != EOIE_SIZE) |
| 3576 | return 0; |
| 3577 | index += sizeof(uint32_t); |
| 3578 | |
| 3579 | /* |
| 3580 | * Validate the offset we're going to look for the first extension |
| 3581 | * signature is after the index header and before the eoie extension. |
| 3582 | */ |
| 3583 | offset = get_be32(index); |
| 3584 | if (mmap + offset < mmap + sizeof(struct cache_header)) |
| 3585 | return 0; |
| 3586 | if (mmap + offset >= eoie) |
| 3587 | return 0; |
| 3588 | index += sizeof(uint32_t); |
| 3589 | |
| 3590 | /* |
| 3591 | * The hash is computed over extension types and their sizes (but not |
| 3592 | * their contents). E.g. if we have "TREE" extension that is N-bytes |
| 3593 | * long, "REUC" extension that is M-bytes long, followed by "EOIE", |
| 3594 | * then the hash would be: |
| 3595 | * |
| 3596 | * SHA-1("TREE" + <binary representation of N> + |
| 3597 | * "REUC" + <binary representation of M>) |
| 3598 | */ |
| 3599 | src_offset = offset; |
| 3600 | the_hash_algo->init_fn(&c); |
| 3601 | while (src_offset < mmap_size - the_hash_algo->rawsz - EOIE_SIZE_WITH_HEADER) { |
| 3602 | /* After an array of active_nr index entries, |
| 3603 | * there can be arbitrary number of extended |
no test coverage detected