Commit 56b203a5 by Patrick Steinhardt

config_file: keep reference to config entries when creating iterator

When creating a configuration file iterator, then we first refresh the
backend and then afterwards duplicate all refreshed configuration
entries into the iterator in order to avoid seeing any concurrent
modifications of the entries while iterating. The duplication of entries
is not guarded, though, as we do not increase the refcount of the
entries that we duplicate right now. This opens us up for a race, as
another thread may concurrently refresh the repository configuration and
thus swap out the current set of entries. As we didn't increase the
refcount, this may lead to the entries being free'd while we iterate
over them in the first thread.

Fix the issue by properly handling the lifecycle of the backend's
entries via `config_file_entries_take` and `git_config_entries_free`,
respectively.
parent 0927156a
......@@ -250,17 +250,19 @@ static int config_file_iterator(
struct git_config_backend *backend)
{
config_file_backend *b = GIT_CONTAINER_OF(backend, config_file_backend, parent);
git_config_entries *entries = NULL;
git_config_entries *dupped = NULL, *entries = NULL;
int error;
if ((error = config_file_refresh(backend)) < 0 ||
(error = git_config_entries_dup(&entries, b->entries)) < 0 ||
(error = git_config_entries_iterator_new(iter, entries)) < 0)
(error = config_file_entries_take(&entries, b)) < 0 ||
(error = git_config_entries_dup(&dupped, entries)) < 0 ||
(error = git_config_entries_iterator_new(iter, dupped)) < 0)
goto out;
out:
/* Let iterator delete duplicated entries when it's done */
git_config_entries_free(entries);
git_config_entries_free(dupped);
return error;
}
......
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