Skip to content

Commit e51e29e

Browse files
committed
config_parse: have git_config_parse own entry value and name
The function `git_config_parse` uses several callbacks to pass data along to the caller as it parses the file. One design shortcoming here is that strings passed to those callbacks are expected to be freed by them, which is really confusing. Fix the issue by changing memory ownership here. Instead of expecting the `on_variable` callbacks to free memory for `git_config_parse`, just do it inside of `git_config_parse`. While this obviously requires a bit more memory allocation churn due to having to copy both name and value at some places, this shouldn't be too much of a burden.
1 parent e212011 commit e51e29e

File tree

3 files changed

+17
-16
lines changed

3 files changed

+17
-16
lines changed

src/config_file.c

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,33 +1022,35 @@ static int parse_conditional_include(git_config_parser *reader,
10221022
static int read_on_variable(
10231023
git_config_parser *reader,
10241024
const char *current_section,
1025-
char *var_name,
1026-
char *var_value,
1025+
const char *var_name,
1026+
const char *var_value,
10271027
const char *line,
10281028
size_t line_len,
10291029
void *data)
10301030
{
10311031
diskfile_parse_state *parse_data = (diskfile_parse_state *)data;
10321032
git_buf buf = GIT_BUF_INIT;
10331033
git_config_entry *entry;
1034+
const char *c;
10341035
int result = 0;
10351036

10361037
GIT_UNUSED(line);
10371038
GIT_UNUSED(line_len);
10381039

1039-
git__strtolower(var_name);
1040-
git_buf_printf(&buf, "%s.%s", current_section, var_name);
1041-
git__free(var_name);
1040+
git_buf_puts(&buf, current_section);
1041+
git_buf_putc(&buf, '.');
1042+
for (c = var_name; *c; c++)
1043+
git_buf_putc(&buf, git__tolower(*c));
10421044

10431045
if (git_buf_oom(&buf)) {
1044-
git__free(var_value);
1046+
git_buf_free(&buf);
10451047
return -1;
10461048
}
10471049

10481050
entry = git__calloc(1, sizeof(git_config_entry));
10491051
GITERR_CHECK_ALLOC(entry);
10501052
entry->name = git_buf_detach(&buf);
1051-
entry->value = var_value;
1053+
entry->value = var_value ? git__strdup(var_value) : NULL;
10521054
entry->level = parse_data->level;
10531055
entry->include_depth = parse_data->depth;
10541056

@@ -1065,7 +1067,6 @@ static int read_on_variable(
10651067
result = parse_conditional_include(reader, parse_data,
10661068
entry->name, entry->value);
10671069

1068-
10691070
return result;
10701071
}
10711072

@@ -1249,8 +1250,8 @@ static int write_on_section(
12491250
static int write_on_variable(
12501251
git_config_parser *reader,
12511252
const char *current_section,
1252-
char *var_name,
1253-
char *var_value,
1253+
const char *var_name,
1254+
const char *var_value,
12541255
const char *line,
12551256
size_t line_len,
12561257
void *data)
@@ -1279,9 +1280,6 @@ static int write_on_variable(
12791280
if (has_matched && write_data->preg != NULL)
12801281
has_matched = (regexec(write_data->preg, var_value, 0, NULL, 0) == 0);
12811282

1282-
git__free(var_name);
1283-
git__free(var_value);
1284-
12851283
/* If this isn't the name/value we're looking for, simply dump the
12861284
* existing data back out and continue on.
12871285
*/

src/config_parse.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ int git_config_parse(
463463
void *data)
464464
{
465465
git_parse_ctx *ctx;
466-
char *current_section = NULL, *var_name, *var_value;
466+
char *current_section = NULL, *var_name = NULL, *var_value = NULL;
467467
int result = 0;
468468

469469
ctx = &parser->ctx;
@@ -508,7 +508,10 @@ int git_config_parse(
508508
default: /* assume variable declaration */
509509
if ((result = parse_variable(parser, &var_name, &var_value)) == 0 && on_variable) {
510510
result = on_variable(parser, current_section, var_name, var_value, line_start, line_len, data);
511+
git__free(var_name);
512+
git__free(var_value);
511513
}
514+
512515
break;
513516
}
514517

src/config_parse.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ typedef int (*git_config_parser_section_cb)(
3636
typedef int (*git_config_parser_variable_cb)(
3737
git_config_parser *parser,
3838
const char *current_section,
39-
char *var_name,
40-
char *var_value,
39+
const char *var_name,
40+
const char *var_value,
4141
const char *line,
4242
size_t line_len,
4343
void *data);

0 commit comments

Comments
 (0)