Fix some diff driver memory leaks
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
diff --git a/src/diff_driver.c b/src/diff_driver.c
index 9c109e7..5d3274a 100644
--- a/src/diff_driver.c
+++ b/src/diff_driver.c
@@ -163,10 +163,10 @@ static int git_diff_driver_load(
memcpy(drv->name, driver_name, namelen);
if ((error = git_buf_printf(&name, "diff.%s.binary", driver_name)) < 0)
- goto fail;
+ goto done;
if ((error = git_config_get_string(&val, cfg, name.ptr)) < 0) {
if (error != GIT_ENOTFOUND)
- goto fail;
+ goto done;
/* diff.<driver>.binary unspecified, so just continue */
giterr_clear();
} else if (git_config_parse_bool(&bval, val) < 0) {
@@ -174,9 +174,8 @@ static int git_diff_driver_load(
giterr_clear();
} else if (bval) {
/* if diff.<driver>.binary is true, just return the binary driver */
- git__free(drv);
*out = &global_drivers[DIFF_DRIVER_BINARY];
- return 0;
+ goto done;
} else {
/* if diff.<driver>.binary is false, force binary checks off */
/* but still may have custom function context patterns, etc. */
@@ -191,7 +190,7 @@ static int git_diff_driver_load(
if ((error = git_config_get_multivar(
cfg, name.ptr, NULL, diff_driver_xfuncname, drv)) < 0) {
if (error != GIT_ENOTFOUND)
- goto fail;
+ goto done;
giterr_clear(); /* no diff.<driver>.xfuncname, so just continue */
}
@@ -200,7 +199,7 @@ static int git_diff_driver_load(
if ((error = git_config_get_multivar(
cfg, name.ptr, NULL, diff_driver_funcname, drv)) < 0) {
if (error != GIT_ENOTFOUND)
- goto fail;
+ goto done;
giterr_clear(); /* no diff.<driver>.funcname, so just continue */
}
@@ -214,12 +213,12 @@ static int git_diff_driver_load(
git_buf_put(&name, "wordregex", strlen("wordregex"));
if ((error = git_config_get_string(&val, cfg, name.ptr)) < 0) {
if (error != GIT_ENOTFOUND)
- goto fail;
+ goto done;
giterr_clear(); /* no diff.<driver>.wordregex, so just continue */
} else if ((error = regcomp(&drv->word_pattern, val, REG_EXTENDED)) != 0) {
/* TODO: warning about bad regex instead of failure */
error = giterr_set_regex(&drv->word_pattern, error);
- goto fail;
+ goto done;
} else {
found_driver = true;
}
@@ -228,21 +227,26 @@ static int git_diff_driver_load(
* diff in drv->other_flags
*/
- /* if no driver config found, fall back on AUTO driver */
+ /* if no driver config found at all, fall back on AUTO driver */
if (!found_driver)
- goto fail;
+ goto done;
/* store driver in registry */
git_strmap_insert(reg->drivers, drv->name, drv, error);
if (error < 0)
- goto fail;
+ goto done;
*out = drv;
- return 0;
-fail:
- git_diff_driver_free(drv);
- *out = &global_drivers[DIFF_DRIVER_AUTO];
+done:
+ git_buf_free(&name);
+
+ if (!*out)
+ *out = &global_drivers[DIFF_DRIVER_AUTO];
+
+ if (drv && drv != *out)
+ git_diff_driver_free(drv);
+
return error;
}
@@ -289,7 +293,7 @@ void git_diff_driver_free(git_diff_driver *driver)
if (!driver)
return;
- for (i = 0; i > git_array_size(driver->fn_patterns); ++i)
+ for (i = 0; i < git_array_size(driver->fn_patterns); ++i)
regfree(git_array_get(driver->fn_patterns, i));
git_array_clear(driver->fn_patterns);
diff --git a/tests-clar/diff/drivers.c b/tests-clar/diff/drivers.c
index 8f7b1f2..06ab2ff 100644
--- a/tests-clar/diff/drivers.c
+++ b/tests-clar/diff/drivers.c
@@ -4,7 +4,6 @@
#include "diff_driver.h"
static git_repository *g_repo = NULL;
-static git_config *g_cfg = NULL;
void test_diff_drivers__initialize(void)
{
@@ -12,15 +11,13 @@ void test_diff_drivers__initialize(void)
void test_diff_drivers__cleanup(void)
{
- git_config_free(g_cfg);
- g_cfg = NULL;
-
cl_git_sandbox_cleanup();
g_repo = NULL;
}
void test_diff_drivers__patterns(void)
{
+ git_config *cfg;
const char *one_sha = "19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13";
git_tree *one;
git_diff_list *diff;
@@ -87,8 +84,9 @@ void test_diff_drivers__patterns(void)
/* let's define that driver */
- cl_git_pass(git_repository_config(&g_cfg, g_repo));
- cl_git_pass(git_config_set_bool(g_cfg, "diff.kipling0.binary", 1));
+ cl_git_pass(git_repository_config(&cfg, g_repo));
+ cl_git_pass(git_config_set_bool(cfg, "diff.kipling0.binary", 1));
+ git_config_free(cfg);
cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL));
cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));
@@ -106,9 +104,10 @@ void test_diff_drivers__patterns(void)
git_diff_driver_registry_free(g_repo->diff_drivers);
g_repo->diff_drivers = NULL;
- cl_git_pass(git_repository_config(&g_cfg, g_repo));
- cl_git_pass(git_config_set_bool(g_cfg, "diff.kipling0.binary", 0));
- cl_git_pass(git_config_set_string(g_cfg, "diff.kipling0.xfuncname", "^H"));
+ cl_git_pass(git_repository_config(&cfg, g_repo));
+ cl_git_pass(git_config_set_bool(cfg, "diff.kipling0.binary", 0));
+ cl_git_pass(git_config_set_string(cfg, "diff.kipling0.xfuncname", "^H"));
+ git_config_free(cfg);
cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL));
cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));