summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Fleischer <cgit@cryptocrack.de>2013-06-04 14:47:53 +0000
committerJason A. Donenfeld <Jason@zx2c4.com>2013-08-12 13:14:10 -0600
commit50e70d32f056c20db760328774d27524648fb739 (patch)
treef11c0bfac7b63143523faaa95e713d52a7cc1cf1
parent820df9c66073b1345397642b46f1885b40b620e3 (diff)
downloadcgit-50e70d32f056c20db760328774d27524648fb739.tar.gz
cgit-50e70d32f056c20db760328774d27524648fb739.tar.bz2
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.c64
-rw-r--r--configfile.h2
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);