diff options
| author | Carlos Martín Nieto <cmn@elego.de> | 2012-06-11 16:28:51 +0200 |
|---|---|---|
| committer | Carlos Martín Nieto <cmn@elego.de> | 2012-06-13 23:26:00 +0200 |
| commit | 49938cad9133dc6bb2120fc3e339cb0132ea71cb (patch) | |
| tree | 919ee06621a64331bf0f619f6d7ee6addf99157a /src/config_file.c | |
| parent | 750be86aedb867a43680f872e1c9824379644739 (diff) | |
| download | libgit2-49938cad9133dc6bb2120fc3e339cb0132ea71cb.tar.gz | |
config: correctly escape quotes in the value
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.
Diffstat (limited to 'src/config_file.c')
| -rw-r--r-- | src/config_file.c | 53 |
1 files changed, 47 insertions, 6 deletions
diff --git a/src/config_file.c b/src/config_file.c index 1c748fad1..fd1aa8d08 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -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; |
