Unverified Commit 826d9a4d by Edward Thomson Committed by GitHub

Merge pull request #4858 from tiennou/fix/index-ext-read

index: preserve extension parsing errors
parents 859d9229 0bf7e043
...@@ -71,6 +71,9 @@ v0.27 + 1 ...@@ -71,6 +71,9 @@ v0.27 + 1
* Revision walks are now more efficient when the output is unsorted; * Revision walks are now more efficient when the output is unsorted;
we now avoid walking all the way to the beginning of history unnecessarily. we now avoid walking all the way to the beginning of history unnecessarily.
* Error-handling around index extension loading has been fixed. We were
previously always misreporting a truncated index (#4858).
### API additions ### API additions
* The index may now be iterated atomically using `git_index_iterator`. * The index may now be iterated atomically using `git_index_iterator`.
......
...@@ -138,7 +138,7 @@ struct reuc_entry_internal { ...@@ -138,7 +138,7 @@ struct reuc_entry_internal {
bool git_index__enforce_unsaved_safety = false; bool git_index__enforce_unsaved_safety = false;
/* local declarations */ /* local declarations */
static size_t read_extension(git_index *index, const char *buffer, size_t buffer_size); static int read_extension(size_t *read_len, git_index *index, const char *buffer, size_t buffer_size);
static int read_header(struct index_header *dest, const void *buffer); static int read_header(struct index_header *dest, const void *buffer);
static int parse_index(git_index *index, const char *buffer, size_t buffer_size); static int parse_index(git_index *index, const char *buffer, size_t buffer_size);
...@@ -2526,7 +2526,7 @@ static int read_header(struct index_header *dest, const void *buffer) ...@@ -2526,7 +2526,7 @@ static int read_header(struct index_header *dest, const void *buffer)
return 0; return 0;
} }
static size_t read_extension(git_index *index, const char *buffer, size_t buffer_size) static int read_extension(size_t *read_len, git_index *index, const char *buffer, size_t buffer_size)
{ {
struct index_extension dest; struct index_extension dest;
size_t total_size; size_t total_size;
...@@ -2539,31 +2539,36 @@ static size_t read_extension(git_index *index, const char *buffer, size_t buffer ...@@ -2539,31 +2539,36 @@ static size_t read_extension(git_index *index, const char *buffer, size_t buffer
if (dest.extension_size > total_size || if (dest.extension_size > total_size ||
buffer_size < total_size || buffer_size < total_size ||
buffer_size - total_size < INDEX_FOOTER_SIZE) buffer_size - total_size < INDEX_FOOTER_SIZE) {
return 0; index_error_invalid("extension is truncated");
return -1;
}
/* optional extension */ /* optional extension */
if (dest.signature[0] >= 'A' && dest.signature[0] <= 'Z') { if (dest.signature[0] >= 'A' && dest.signature[0] <= 'Z') {
/* tree cache */ /* tree cache */
if (memcmp(dest.signature, INDEX_EXT_TREECACHE_SIG, 4) == 0) { if (memcmp(dest.signature, INDEX_EXT_TREECACHE_SIG, 4) == 0) {
if (git_tree_cache_read(&index->tree, buffer + 8, dest.extension_size, &index->tree_pool) < 0) if (git_tree_cache_read(&index->tree, buffer + 8, dest.extension_size, &index->tree_pool) < 0)
return 0; return -1;
} else if (memcmp(dest.signature, INDEX_EXT_UNMERGED_SIG, 4) == 0) { } else if (memcmp(dest.signature, INDEX_EXT_UNMERGED_SIG, 4) == 0) {
if (read_reuc(index, buffer + 8, dest.extension_size) < 0) if (read_reuc(index, buffer + 8, dest.extension_size) < 0)
return 0; return -1;
} else if (memcmp(dest.signature, INDEX_EXT_CONFLICT_NAME_SIG, 4) == 0) { } else if (memcmp(dest.signature, INDEX_EXT_CONFLICT_NAME_SIG, 4) == 0) {
if (read_conflict_names(index, buffer + 8, dest.extension_size) < 0) if (read_conflict_names(index, buffer + 8, dest.extension_size) < 0)
return 0; return -1;
} }
/* else, unsupported extension. We cannot parse this, but we can skip /* else, unsupported extension. We cannot parse this, but we can skip
* it by returning `total_size */ * it by returning `total_size */
} else { } else {
/* we cannot handle non-ignorable extensions; /* we cannot handle non-ignorable extensions;
* in fact they aren't even defined in the standard */ * in fact they aren't even defined in the standard */
return 0; git_error_set(GIT_ERROR_INDEX, "unsupported mandatory extension: '%.4s'", dest.signature);
return -1;
} }
return total_size; *read_len = total_size;
return 0;
} }
static int parse_index(git_index *index, const char *buffer, size_t buffer_size) static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
...@@ -2645,11 +2650,7 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size) ...@@ -2645,11 +2650,7 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
while (buffer_size > INDEX_FOOTER_SIZE) { while (buffer_size > INDEX_FOOTER_SIZE) {
size_t extension_size; size_t extension_size;
extension_size = read_extension(index, buffer, buffer_size); if ((error = read_extension(&extension_size, index, buffer, buffer_size)) < 0) {
/* see if we have read any bytes from the extension */
if (extension_size == 0) {
error = index_error_invalid("extension is truncated");
goto done; goto done;
} }
......
#include "clar_libgit2.h"
#include "index.h"
static git_repository *g_repo;
void test_index_splitindex__initialize(void)
{
g_repo = cl_git_sandbox_init("splitindex");
}
void test_index_splitindex__cleanup(void)
{
cl_git_sandbox_cleanup();
}
void test_index_splitindex__fail_on_open(void)
{
git_index *idx;
cl_git_fail_with(-1, git_repository_index(&idx, g_repo));
cl_assert_equal_s(git_error_last()->message, "unsupported mandatory extension: 'link'");
}
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
splitIndex = true
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment