diff options
author | Lukas Fleischer <cgit@cryptocrack.de> | 2013-06-04 18:47:53 +0400 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2013-08-12 23:14:10 +0400 |
commit | 50e70d32f056c20db760328774d27524648fb739 (patch) | |
tree | f11c0bfac7b63143523faaa95e713d52a7cc1cf1 | |
parent | 820df9c66073b1345397642b46f1885b40b620e3 (diff) |
Use strbuf for reading configuration files
Use struct strbuf from Git instead of fixed-size buffers to remove the
limit on the length of configuration file lines and refactor
read_config_line() to improve readability.
Note that this also fixes a buffer overflow that existed with the
original fixed-size buffer implementation.
Signed-off-by: Lukas Fleischer <cgit@cryptocrack.de>
-rw-r--r-- | configfile.c | 64 | ||||
-rw-r--r-- | configfile.h | 2 |
2 files changed, 35 insertions, 31 deletions
diff --git a/configfile.c b/configfile.c index d98989c..31fe5c8 100644 --- a/configfile.c +++ b/configfile.c @@ -31,45 +31,45 @@ static void skip_line(FILE *f) ; } -static int read_config_line(FILE *f, char *line, const char **value, int bufsize) +static int read_config_line(FILE *f, struct strbuf *name, struct strbuf *value) { - int i = 0, isname = 0; + int c = next_char(f); - *value = NULL; - while (i < bufsize - 1) { - int c = next_char(f); - if (!isname && (c == '#' || c == ';')) { - skip_line(f); - continue; - } - if (!isname && isspace(c)) - continue; + strbuf_reset(name); + strbuf_reset(value); - if (c == '=' && !*value) { - line[i] = 0; - *value = &line[i + 1]; - } else if (c == '\n' && !isname) { - i = 0; - continue; - } else if (c == '\n' || c == EOF) { - line[i] = 0; + /* Skip comments and preceding spaces. */ + for(;;) { + if (c == '#' || c == ';') + skip_line(f); + else if (!isspace(c)) break; - } else { - line[i] = c; - } - isname = 1; - i++; + c = next_char(f); } - line[i + 1] = 0; - return i; + + /* Read variable name. */ + while (c != '=') { + if (c == '\n' || c == EOF) + return 0; + strbuf_addch(name, c); + c = next_char(f); + } + + /* Read variable value. */ + c = next_char(f); + while (c != '\n' && c != EOF) { + strbuf_addch(value, c); + c = next_char(f); + } + + return 1; } int parse_configfile(const char *filename, configfile_value_fn fn) { static int nesting; - int len; - char line[256]; - const char *value; + struct strbuf name = STRBUF_INIT; + struct strbuf value = STRBUF_INIT; FILE *f; /* cancel deeply nested include-commands */ @@ -78,10 +78,12 @@ int parse_configfile(const char *filename, configfile_value_fn fn) if (!(f = fopen(filename, "r"))) return -1; nesting++; - while ((len = read_config_line(f, line, &value, sizeof(line))) > 0) - fn(line, value); + while (read_config_line(f, &name, &value)) + fn(name.buf, value.buf); nesting--; fclose(f); + strbuf_release(&name); + strbuf_release(&value); return 0; } diff --git a/configfile.h b/configfile.h index 04235e5..af7ca19 100644 --- a/configfile.h +++ b/configfile.h @@ -1,6 +1,8 @@ #ifndef CONFIGFILE_H #define CONFIGFILE_H +#include "cgit.h" + typedef void (*configfile_value_fn)(const char *name, const char *value); extern int parse_configfile(const char *filename, configfile_value_fn fn); |