int git_index__parse(git_index *index, const char *buffer, size_t buffer_size) { unsigned int i; struct index_header header; git_oid checksum_calculated, checksum_expected; #define seek_forward(_increase) { \ if (_increase >= buffer_size) \ return GIT_EOBJCORRUPTED; \ buffer += _increase; \ buffer_size -= _increase;\ } if (buffer_size < INDEX_HEADER_SIZE + INDEX_FOOTER_SIZE) return GIT_EOBJCORRUPTED; /* Precalculate the SHA1 of the files's contents -- we'll match it to * the provided SHA1 in the footer */ git_hash_buf(&checksum_calculated, (const void *)buffer, buffer_size - INDEX_FOOTER_SIZE); /* Parse header */ if (read_header(&header, buffer) < 0) return GIT_EOBJCORRUPTED; seek_forward(INDEX_HEADER_SIZE); index->entry_count = header.entry_count; /* If there is already a entires array, reuse it if it can hold all the * entries. If not, free and reallocate */ if (index->entry_count > index->entries_size) { free(index->entries); index->entries_size = (uint32_t)(index->entry_count * 1.3f); index->entries = git__malloc(index->entries_size * sizeof(git_index_entry)); } /* Parse all the entries */ for (i = 0; i < index->entry_count && buffer_size > INDEX_FOOTER_SIZE; ++i) { size_t entry_size; entry_size = read_entry(&index->entries[i], buffer, buffer_size); /* 0 bytes read means an object corruption */ if (entry_size == 0) return GIT_EOBJCORRUPTED; seek_forward(entry_size); } if (i != index->entry_count) return GIT_EOBJCORRUPTED; /* There's still space for some extensions! */ while (buffer_size > INDEX_FOOTER_SIZE) { size_t extension_size; extension_size = read_extension(index, buffer, buffer_size); /* see if we have read any bytes from the extension */ if (extension_size == 0) return GIT_EOBJCORRUPTED; seek_forward(extension_size); } if (buffer_size != INDEX_FOOTER_SIZE) return GIT_EOBJCORRUPTED; /* 160-bit SHA-1 over the content of the index file before this checksum. */ git_oid_mkraw(&checksum_expected, (const unsigned char *)buffer); if (git_oid_cmp(&checksum_calculated, &checksum_expected) != 0) return GIT_EOBJCORRUPTED; #undef seek_forward return 0; }
static int parse_index(git_index *index, const char *buffer, size_t buffer_size) { unsigned int i; struct index_header header; git_oid checksum_calculated, checksum_expected; #define seek_forward(_increase) { \ if (_increase >= buffer_size) \ return git__throw(GIT_EOBJCORRUPTED, "Failed to seek forward. Buffer size exceeded"); \ buffer += _increase; \ buffer_size -= _increase;\ } if (buffer_size < INDEX_HEADER_SIZE + INDEX_FOOTER_SIZE) return git__throw(GIT_EOBJCORRUPTED, "Failed to parse index. Buffer too small"); /* Precalculate the SHA1 of the files's contents -- we'll match it to * the provided SHA1 in the footer */ git_hash_buf(&checksum_calculated, buffer, buffer_size - INDEX_FOOTER_SIZE); /* Parse header */ if (read_header(&header, buffer) < GIT_SUCCESS) return git__throw(GIT_EOBJCORRUPTED, "Failed to parse index. Header is corrupted"); seek_forward(INDEX_HEADER_SIZE); git_vector_clear(&index->entries); /* Parse all the entries */ for (i = 0; i < header.entry_count && buffer_size > INDEX_FOOTER_SIZE; ++i) { size_t entry_size; git_index_entry *entry; entry = git__malloc(sizeof(git_index_entry)); if (entry == NULL) return GIT_ENOMEM; entry_size = read_entry(entry, buffer, buffer_size); /* 0 bytes read means an object corruption */ if (entry_size == 0) return git__throw(GIT_EOBJCORRUPTED, "Failed to parse index. Entry size is zero"); if (git_vector_insert(&index->entries, entry) < GIT_SUCCESS) return GIT_ENOMEM; seek_forward(entry_size); } if (i != header.entry_count) return git__throw(GIT_EOBJCORRUPTED, "Failed to parse index. Header entries changed while parsing"); /* There's still space for some extensions! */ while (buffer_size > INDEX_FOOTER_SIZE) { size_t extension_size; extension_size = read_extension(index, buffer, buffer_size); /* see if we have read any bytes from the extension */ if (extension_size == 0) return git__throw(GIT_EOBJCORRUPTED, "Failed to parse index. Extension size is zero"); seek_forward(extension_size); } if (buffer_size != INDEX_FOOTER_SIZE) return git__throw(GIT_EOBJCORRUPTED, "Failed to parse index. Buffer size does not match index footer size"); /* 160-bit SHA-1 over the content of the index file before this checksum. */ git_oid_fromraw(&checksum_expected, (const unsigned char *)buffer); if (git_oid_cmp(&checksum_calculated, &checksum_expected) != 0) return git__throw(GIT_EOBJCORRUPTED, "Failed to parse index. Calculated checksum does not match expected checksum"); #undef seek_forward /* force sorting in the vector: the entries are * assured to be sorted on the index */ index->entries.sorted = 1; return GIT_SUCCESS; }