Commit fee8572c6d (config: avoid using the global variable `store`,
2018-04-09) dropped the staticness of a certain struct, instead letting
the users create an instance on the stack and pass around a pointer.

We do not free the memory that the struct tracks. When the struct was
static, the memory would always be reachable. Now that we keep the
struct on the stack, though, as soon as we return, it goes out of scope
and we leak the memory it points to.

Introduce and use a small helper function `config_store_data_clear()` to
plug these leaks. This should be safe. The memory tracked here is config
parser events. Once the users (`git_config_set_multivar_in_file_gently()`
and `git_config_copy_or_rename_section_in_file()` at the moment) are
done, no-one should be holding on to a pointer into this memory.

Signed-off-by: Martin Ågren <martin.ag...@gmail.com>
---
 config.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/config.c b/config.c
index 6f8f1d8c11..83d7d0851a 100644
--- a/config.c
+++ b/config.c
@@ -2333,6 +2333,13 @@ struct config_store_data {
        unsigned int key_seen:1, section_seen:1, is_keys_section:1;
 };
 
+void config_store_data_clear(struct config_store_data *store)
+{
+       free(store->parsed);
+       free(store->seen);
+       memset(store, 0, sizeof(*store));
+}
+
 static int matches(const char *key, const char *value,
                   const struct config_store_data *store)
 {
@@ -2887,6 +2894,7 @@ int git_config_set_multivar_in_file_gently(const char 
*config_filename,
                munmap(contents, contents_sz);
        if (in_fd >= 0)
                close(in_fd);
+       config_store_data_clear(&store);
        return ret;
 
 write_err_out:
@@ -3127,6 +3135,7 @@ static int 
git_config_copy_or_rename_section_in_file(const char *config_filename
        rollback_lock_file(&lock);
 out_no_rollback:
        free(filename_buf);
+       config_store_data_clear(&store);
        return ret;
 }
 
-- 
2.17.0.583.g9a75a153ac

Reply via email to