]> git.cameronkatri.com Git - cgit.git/commitdiff
Use strbuf for reading configuration files
authorLukas Fleischer <cgit@cryptocrack.de>
Tue, 4 Jun 2013 14:47:53 +0000 (14:47 +0000)
committerJason A. Donenfeld <Jason@zx2c4.com>
Mon, 12 Aug 2013 19:14:10 +0000 (13:14 -0600)
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>
configfile.c
configfile.h

index d98989c4312aed59e9a6a45aee3b603c8ac1c48f..31fe5c88915a418fbec3dfb58d44fc67f6ac6b0d 100644 (file)
@@ -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;
 }
 
index 04235e547c87201249b8fab47f3eff7be843bcd7..af7ca1973590cd31a45c0f3733d31a5da56ec9e8 100644 (file)
@@ -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);