config: validate config keys
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
diff --git a/src/config_file.c b/src/config_file.c
index 7c6cb81..0f9141a 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -1723,9 +1723,47 @@ static int parse_multiline_variable(struct reader *reader, git_buf *value, int i
return 0;
}
+GIT_INLINE(bool) is_namechar(char c)
+{
+ return isalnum(c) || c == '-';
+}
+
+static int parse_name(
+ char **name, const char **value, struct reader *reader, const char *line)
+{
+ const char *name_end = line, *value_start;
+
+ *name = NULL;
+ *value = NULL;
+
+ while (*name_end && is_namechar(*name_end))
+ name_end++;
+
+ if (line == name_end) {
+ set_parse_error(reader, 0, "Invalid configuration key");
+ return -1;
+ }
+
+ value_start = name_end;
+
+ while (*value_start && git__isspace(*value_start))
+ value_start++;
+
+ if (*value_start == '=') {
+ *value = value_start + 1;
+ } else if (*value_start) {
+ set_parse_error(reader, 0, "Invalid configuration key");
+ return -1;
+ }
+
+ if ((*name = git__strndup(line, name_end - line)) == NULL)
+ return -1;
+
+ return 0;
+}
+
static int parse_variable(struct reader *reader, char **var_name, char **var_value)
{
- const char *var_end = NULL;
const char *value_start = NULL;
char *line;
int quote_count;
@@ -1737,18 +1775,8 @@ static int parse_variable(struct reader *reader, char **var_name, char **var_val
quote_count = strip_comments(line, 0);
- var_end = strchr(line, '=');
-
- if (var_end == NULL)
- var_end = strchr(line, '\0');
- else
- value_start = var_end + 1;
-
- do var_end--;
- while (var_end>line && git__isspace(*var_end));
-
- *var_name = git__strndup(line, var_end - line + 1);
- GITERR_CHECK_ALLOC(*var_name);
+ if (parse_name(var_name, &value_start, reader, line) < 0)
+ return -1;
/* If there is no value, boolean true is assumed */
*var_value = NULL;