]> git.proxmox.com Git - libgit2.git/commitdiff
config: correctly escape quotes in the value
authorCarlos Martín Nieto <cmn@elego.de>
Mon, 11 Jun 2012 14:28:51 +0000 (16:28 +0200)
committerCarlos Martín Nieto <cmn@elego.de>
Wed, 13 Jun 2012 21:26:00 +0000 (23:26 +0200)
When a configuration option is set, we didn't check to see whether
there was any escaping needed. Escape the available characters so we
can unescape them correctly when we read them.

src/config_file.c

index 1c748fad11cb70c87c17324dc497848bb772107d..fd1aa8d086320a48181d83a76bbc75a365e3181e 100644 (file)
@@ -87,6 +87,7 @@ typedef struct {
 static int config_parse(diskfile_backend *cfg_file);
 static int parse_variable(diskfile_backend *cfg, char **var_name, char **var_value);
 static int config_write(diskfile_backend *cfg, const char *key, const regex_t *preg, const char *value);
+static char *escape_value(const char *ptr);
 
 static void set_parse_error(diskfile_backend *backend, int col, const char *error_str)
 {
@@ -212,9 +213,9 @@ static int config_set(git_config_file *cfg, const char *name, const char *value)
 {
        cvar_t *var = NULL, *old_var;
        diskfile_backend *b = (diskfile_backend *)cfg;
-       char *key;
+       char *key, *esc_value = NULL;
        khiter_t pos;
-       int rval;
+       int rval, ret;
 
        if (normalize_name(name, &key) < 0)
                return -1;
@@ -237,12 +238,17 @@ static int config_set(git_config_file *cfg, const char *name, const char *value)
                if (value) {
                        tmp = git__strdup(value);
                        GITERR_CHECK_ALLOC(tmp);
+                       esc_value = escape_value(value);
+                       GITERR_CHECK_ALLOC(esc_value);
                }
 
                git__free(existing->value);
                existing->value = tmp;
 
-               return config_write(b, existing->key, NULL, value);
+               ret = config_write(b, existing->key, NULL, esc_value);
+
+               git__free(esc_value);
+               return ret;
        }
 
        var = git__malloc(sizeof(cvar_t));
@@ -256,13 +262,17 @@ static int config_set(git_config_file *cfg, const char *name, const char *value)
        if (value) {
                var->value = git__strdup(value);
                GITERR_CHECK_ALLOC(var->value);
+               esc_value = escape_value(value);
+               GITERR_CHECK_ALLOC(esc_value);
        }
 
-       if (config_write(b, key, NULL, value) < 0) {
+       if (config_write(b, key, NULL, esc_value) < 0) {
+               git__free(esc_value);
                cvar_free(var);
                return -1;
        }
 
+       git__free(esc_value);
        git_strmap_insert2(b->values, key, var, old_var, rval);
        if (rval < 0)
                return -1;
@@ -1155,13 +1165,44 @@ rewrite_fail:
        return -1;
 }
 
+static const char *escapes = "ntb\"\\";
+static const char *escaped = "\n\t\b\"\\";
+
+/* Escape the values to write them to the file */
+static char *escape_value(const char *ptr)
+{
+       git_buf buf = GIT_BUF_INIT;
+       size_t len;
+       const char *esc;
+
+       assert(ptr);
+
+       len = strlen(ptr);
+       git_buf_grow(&buf, len);
+
+       while (*ptr != '\0') {
+               if ((esc = strchr(escaped, *ptr)) != NULL) {
+                       git_buf_putc(&buf, '\\');
+                       git_buf_putc(&buf, escapes[esc - escaped]);
+               } else {
+                       git_buf_putc(&buf, *ptr);
+               }
+               ptr++;
+       }
+
+       if (git_buf_oom(&buf)) {
+               git_buf_free(&buf);
+               return NULL;
+       }
+
+       return git_buf_detach(&buf);
+}
+
 /* '\"' -> '"' etc */
 static char *fixup_line(const char *ptr, int quote_count)
 {
        char *str = git__malloc(strlen(ptr) + 1);
        char *out = str, *esc;
-       const char *escapes = "ntb\"\\";
-       const char *escaped = "\n\t\b\"\\";
 
        if (str == NULL)
                return NULL;