summaryrefslogtreecommitdiff
path: root/src/config_file.c
diff options
context:
space:
mode:
authorCarlos Martín Nieto <cmn@elego.de>2012-06-11 16:28:51 +0200
committerCarlos Martín Nieto <cmn@elego.de>2012-06-13 23:26:00 +0200
commit49938cad9133dc6bb2120fc3e339cb0132ea71cb (patch)
tree919ee06621a64331bf0f619f6d7ee6addf99157a /src/config_file.c
parent750be86aedb867a43680f872e1c9824379644739 (diff)
downloadlibgit2-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.c53
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;