Code

conf: extract name and value from the input line in-place
authorMax Kellermann <max.kellermann@gmail.com>
Tue, 28 Mar 2017 20:52:22 +0000 (22:52 +0200)
committerMax Kellermann <max.kellermann@gmail.com>
Tue, 28 Mar 2017 21:22:17 +0000 (23:22 +0200)
No copies to a stack buffer.

src/conf.c

index ae362f142d67f6363e3eceec352b6afde1f2e254..b8e9c5d7cdc1caad062d28de492277d0226f30ef 100644 (file)
@@ -121,6 +121,29 @@ print_error(const char *msg, const char *input)
                _("Error"), msg, input);
 }
 
+gcc_const
+static bool
+is_word_char(char ch)
+{
+       return g_ascii_isalnum(ch) || ch == '-' || ch == '_';
+}
+
+static char *
+after_unquoted_word(char *p)
+{
+       if (!is_word_char(*p)) {
+               print_error(_("Word expected"), p);
+               return NULL;
+       }
+
+       ++p;
+
+       while (is_word_char(*p))
+               ++p;
+
+       return p;
+}
+
 static int
 parse_key_value(char *str, char **end)
 {
@@ -390,25 +413,25 @@ get_search_mode(char *value)
 static bool
 parse_line(char *line)
 {
-       size_t len = strlen(line), i = 0, j = 0;
-
        /* get the name part */
-       char name[MAX_LINE_LENGTH];
-       while (i < len && line[i] != '=' && !g_ascii_isspace(line[i]))
-               name[j++] = line[i++];
+       char *const name = line;
+       char *const name_end = after_unquoted_word(line);
+       if (name_end == NULL)
+               return false;
 
-       name[j] = '\0';
+       line = skip_spaces(name_end);
+       if (*line == '=') {
+               ++line;
+               line = skip_spaces(line);
+       } else if (line == name_end) {
+               print_error(_("'=' expected"), name_end);
+               return false;
+       }
 
-       /* skip '=' and whitespace */
-       while (i < len && (line[i] == '=' || g_ascii_isspace(line[i])))
-               i++;
+       *name_end = 0;
 
        /* get the value part */
-       char value[MAX_LINE_LENGTH];
-       j = 0;
-       while (i < len)
-               value[j++] = line[i++];
-       value[j] = '\0';
+       char *const value = line;
 
        /* key definition */
        if (!strcasecmp(CONF_KEY_DEFINITION, name))