[PATCH] Use strbuf for reading configuration files
John Keeping
john at keeping.me.uk
Tue Jun 4 20:23:03 CEST 2013
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?
> 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