git-config: fix regexp memory leaks on error conditions

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>
This commit is contained in:
Jeff King 2012-10-23 15:40:06 -04:00
parent 35998c8938
commit 97ed50f93b
2 changed files with 14 additions and 10 deletions

View 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;
}

View File

@ -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;
}