diff options
| author | Etienne Samson <samson.etienne@gmail.com> | 2019-01-24 12:12:04 +0100 |
|---|---|---|
| committer | Etienne Samson <samson.etienne@gmail.com> | 2019-01-24 12:12:04 +0100 |
| commit | 0bf7e0433dc0a5a71b4ed6575b84c552825e82fd (patch) | |
| tree | 4c118b4b48ea887c6d7a420380a689fda53774f9 /src/index.c | |
| parent | 635693d3bc55770ec7a6640ba3f2f0ee434a6042 (diff) | |
| download | libgit2-0bf7e0433dc0a5a71b4ed6575b84c552825e82fd.tar.gz | |
index: preserve extension parsing errors
Previously, we would clobber any extension-specific error message with
an "extension is truncated" message. This makes `read_extension`
correctly preserve those errors, takes responsibility for truncation
errors, and adds a new message with the actual extension signature for
unsupported mandatory extensions.
Diffstat (limited to 'src/index.c')
| -rw-r--r-- | src/index.c | 29 |
1 files changed, 15 insertions, 14 deletions
diff --git a/src/index.c b/src/index.c index 677faea47..8b753234f 100644 --- a/src/index.c +++ b/src/index.c @@ -138,7 +138,7 @@ struct reuc_entry_internal { bool git_index__enforce_unsaved_safety = false; /* 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 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) 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; size_t total_size; @@ -2539,31 +2539,36 @@ static size_t read_extension(git_index *index, const char *buffer, size_t buffer if (dest.extension_size > total_size || buffer_size < total_size || - buffer_size - total_size < INDEX_FOOTER_SIZE) - return 0; + buffer_size - total_size < INDEX_FOOTER_SIZE) { + index_error_invalid("extension is truncated"); + return -1; + } /* optional extension */ if (dest.signature[0] >= 'A' && dest.signature[0] <= 'Z') { /* tree cache */ 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) - return 0; + return -1; } else if (memcmp(dest.signature, INDEX_EXT_UNMERGED_SIG, 4) == 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) { 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 * it by returning `total_size */ } else { /* we cannot handle non-ignorable extensions; * 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) @@ -2645,11 +2650,7 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size) 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) { - error = index_error_invalid("extension is truncated"); + if ((error = read_extension(&extension_size, index, buffer, buffer_size)) < 0) { goto done; } |
