git-config: fix regexp memory leaks on error conditions
authorJeff King <peff@peff.net>
Tue, 23 Oct 2012 19:40:06 +0000 (15:40 -0400)
committerJeff King <peff@peff.net>
Wed, 24 Oct 2012 07:36:54 +0000 (03:36 -0400)
The get_value function has a goto label for cleaning up on
errors, but it only cleans up half of what the function
might allocate. Let's also clean up the key and regexp
variables there.

Note that we need to take special care when compiling the
regex fails to clean it up ourselves, since it is in a
half-constructed state (we would want to free it, but not
regfree it).

Similarly, we fix git_config_parse_key to return NULL when
it fails, not a pointer to some already-freed memory.

Signed-off-by: Jeff King <peff@peff.net>
builtin/config.c
config.c
index e660d48300b874fe422e813dbcd5f5eecab31e56..60d36e734b1872b547d208c0979210941fcccf5f 100644 (file)
@@ -195,7 +195,8 @@ static int get_value(const char *key_, const char *regex_)
                key_regexp = (regex_t*)xmalloc(sizeof(regex_t));
                if (regcomp(key_regexp, key, REG_EXTENDED)) {
                        fprintf(stderr, "Invalid key pattern: %s\n", key_);
-                       free(key);
+                       free(key_regexp);
+                       key_regexp = NULL;
                        ret = CONFIG_INVALID_PATTERN;
                        goto free_strings;
                }
@@ -215,6 +216,8 @@ static int get_value(const char *key_, const char *regex_)
                regexp = (regex_t*)xmalloc(sizeof(regex_t));
                if (regcomp(regexp, regex_, REG_EXTENDED)) {
                        fprintf(stderr, "Invalid pattern: %s\n", regex_);
+                       free(regexp);
+                       regexp = NULL;
                        ret = CONFIG_INVALID_PATTERN;
                        goto free_strings;
                }
@@ -247,6 +250,15 @@ static int get_value(const char *key_, const char *regex_)
        if (!do_all && !seen && system_wide)
                git_config_from_file(fn, system_wide, data);
 
+       if (do_all)
+               ret = !seen;
+       else
+               ret = (seen == 1) ? 0 : seen > 1 ? 2 : 1;
+
+free_strings:
+       free(repo_config);
+       free(global);
+       free(xdg);
        free(key);
        if (key_regexp) {
                regfree(key_regexp);
@@ -257,15 +269,6 @@ static int get_value(const char *key_, const char *regex_)
                free(regexp);
        }
 
-       if (do_all)
-               ret = !seen;
-       else
-               ret = (seen == 1) ? 0 : seen > 1 ? 2 : 1;
-
-free_strings:
-       free(repo_config);
-       free(global);
-       free(xdg);
        return ret;
 }
 
index 08e47e2e48a5bd310025752ee5ecdce81721b34d..2fbe634b173d9787f2bbeba0e4bc6bf4e89701a5 100644 (file)
--- a/config.c
+++ b/config.c
@@ -1280,6 +1280,7 @@ int git_config_parse_key(const char *key, char **store_key, int *baselen_)
 
 out_free_ret_1:
        free(*store_key);
+       *store_key = NULL;
        return -CONFIG_INVALID_KEY;
 }