[PATCH] Use strbuf for reading configuration files
Lukas Fleischer
cgit at cryptocrack.de
Wed Jun 5 13:20:19 CEST 2013
On Tue, Jun 04, 2013 at 07:23:03PM +0100, John Keeping wrote:
> On Tue, Jun 04, 2013 at 04:47:53PM +0200, Lukas Fleischer wrote:
> > 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 at cryptocrack.de>
> > ---
>
> Is there any reason not to use strbuf_getline and
> string_list_split_in_place if we're using strbuf here?
* We would need to deal with CRLF separately (check what next_char()
currently does).
* I don't think it is much shorter or significantly improves
readability.
* It might be a tad slower (we need to look for the delimiter after
reading the whole line vs. doing it on the fly).
* Git uses strbuf_addch() in their configuration file parser as well
(although their format is a tad more complex and there might be other
reasons for using it there).
I will resubmit v2 that still uses strbuf_addch() -- feel free to submit
an improved version that uses strbuf_getline() and
string_list_split_in_place() :)
>
> > configfile.c | 65 ++++++++++++++++++++++++++++++------------------------------
> > configfile.h | 2 ++
> > 2 files changed, 35 insertions(+), 32 deletions(-)
> >
> > diff --git a/configfile.c b/configfile.c
> > index d98989c..e6ad1d6 100644
> > --- a/configfile.c
> > +++ b/configfile.c
> > @@ -31,45 +31,44 @@ 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;
> > - break;
> > - } else {
> > - line[i] = c;
> > - }
> > - isname = 1;
> > - i++;
> > + /* Skip comments and preceding spaces. */
> > + while (c == '#' || c == ';') {
> > + skip_line(f);
> > + c = next_char(f);
> > + }
> > + while (isspace(c))
> > + c = next_char(f);
> > +
> > + /* Read variable name. */
> > + while (c != '=') {
> > + if (c == '\n' || c == EOF)
> > + return 0;
> > + strbuf_addch(name, c);
> > + c = next_char(f);
> > }
> > - line[i + 1] = 0;
> > - return i;
> > +
> > + /* 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 +77,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);
> > --
> > 1.8.3.450.gf3f2a46
More information about the CGit
mailing list