Commit 76182e84 by Patrick Steinhardt

config_entries: fix possible segfault when duplicating entries

When duplicating a configuration entry, we allocate a new entry but do
not verify that we get a valid pointer back. As we're dereferencing the
pointer afterwards, we might thus run into a segfault in out-of-memory
situations.

Extract a new function `git_config_entries_dup_entry` that handles the
complete entry duplication. Fix the error by using
`GIT_ERROR_CHECK_ALLOC`.
parent e3adc99e
...@@ -67,6 +67,36 @@ int git_config_entries_new(git_config_entries **out) ...@@ -67,6 +67,36 @@ int git_config_entries_new(git_config_entries **out)
return error; return error;
} }
int git_config_entries_dup_entry(git_config_entries *entries, const git_config_entry *entry)
{
git_config_entry *duplicated;
int error;
duplicated = git__calloc(1, sizeof(git_config_entry));
GIT_ERROR_CHECK_ALLOC(duplicated);
duplicated->name = git__strdup(entry->name);
GIT_ERROR_CHECK_ALLOC(duplicated->name);
if (entry->value) {
duplicated->value = git__strdup(entry->value);
GIT_ERROR_CHECK_ALLOC(duplicated->value);
}
duplicated->level = entry->level;
duplicated->include_depth = entry->include_depth;
if ((error = git_config_entries_append(entries, duplicated)) < 0)
goto out;
out:
if (error && duplicated) {
git__free((char *) duplicated->name);
git__free((char *) duplicated->value);
git__free(duplicated);
}
return error;
}
int git_config_entries_dup(git_config_entries **out, git_config_entries *entries) int git_config_entries_dup(git_config_entries **out, git_config_entries *entries)
{ {
git_config_entries *result = NULL; git_config_entries *result = NULL;
...@@ -76,22 +106,9 @@ int git_config_entries_dup(git_config_entries **out, git_config_entries *entries ...@@ -76,22 +106,9 @@ int git_config_entries_dup(git_config_entries **out, git_config_entries *entries
if ((error = git_config_entries_new(&result)) < 0) if ((error = git_config_entries_new(&result)) < 0)
goto out; goto out;
for (head = entries->list; head; head = head->next) { for (head = entries->list; head; head = head->next)
git_config_entry *dup; if ((git_config_entries_dup_entry(result, head->entry)) < 0)
dup = git__calloc(1, sizeof(git_config_entry));
dup->name = git__strdup(head->entry->name);
GIT_ERROR_CHECK_ALLOC(dup->name);
if (head->entry->value) {
dup->value = git__strdup(head->entry->value);
GIT_ERROR_CHECK_ALLOC(dup->value);
}
dup->level = head->entry->level;
dup->include_depth = head->entry->include_depth;
if ((error = git_config_entries_append(result, dup)) < 0)
goto out; goto out;
}
*out = result; *out = result;
result = NULL; result = NULL;
......
...@@ -14,6 +14,7 @@ typedef struct git_config_entries git_config_entries; ...@@ -14,6 +14,7 @@ typedef struct git_config_entries git_config_entries;
int git_config_entries_new(git_config_entries **out); int git_config_entries_new(git_config_entries **out);
int git_config_entries_dup(git_config_entries **out, git_config_entries *entries); int git_config_entries_dup(git_config_entries **out, git_config_entries *entries);
int git_config_entries_dup_entry(git_config_entries *entries, const git_config_entry *entry);
void git_config_entries_incref(git_config_entries *entries); void git_config_entries_incref(git_config_entries *entries);
void git_config_entries_free(git_config_entries *entries); void git_config_entries_free(git_config_entries *entries);
/* Add or append the new config option */ /* Add or append the new config option */
......
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