Skip to content

Commit 0971e99

Browse files
bdwaltongitster
authored andcommitted
Remove the hard coded length limit on variable names in config files
Previously while reading the variable names in config files, there was a 256 character limit with at most 128 of those characters being used by the section header portion of the variable name. This limitation was only enforced while reading the config files. It was possible to write a config file that was not subsequently readable. Instead of enforcing this limitation for both reading and writing, remove it entirely by changing the var member of the config_file struct to a strbuf instead of a fixed length buffer. Update all of the parsing functions in config.c to use the strbuf instead of the static buffer. The parsing functions that returned the base length of the variable name now return simply 0 for success and -1 for failure. The base length information is obtained through the strbuf's len member. We now send the buf member of the strbuf to external callback functions to preserve the external api. None of the external callers rely on the old size limitation for sizing their own buffers so removing the limit should have no externally visible effect. Signed-off-by: Ben Walton <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent d8cf053 commit 0971e99

File tree

1 file changed

+29
-30
lines changed

1 file changed

+29
-30
lines changed

config.c

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,14 @@
1010
#include "strbuf.h"
1111
#include "quote.h"
1212

13-
#define MAXNAME (256)
14-
1513
typedef struct config_file {
1614
struct config_file *prev;
1715
FILE *f;
1816
const char *name;
1917
int linenr;
2018
int eof;
2119
struct strbuf value;
22-
char var[MAXNAME];
20+
struct strbuf var;
2321
} config_file;
2422

2523
static config_file *cf;
@@ -260,7 +258,7 @@ static inline int iskeychar(int c)
260258
return isalnum(c) || c == '-';
261259
}
262260

263-
static int get_value(config_fn_t fn, void *data, char *name, unsigned int len)
261+
static int get_value(config_fn_t fn, void *data, struct strbuf *name)
264262
{
265263
int c;
266264
char *value;
@@ -272,11 +270,9 @@ static int get_value(config_fn_t fn, void *data, char *name, unsigned int len)
272270
break;
273271
if (!iskeychar(c))
274272
break;
275-
name[len++] = tolower(c);
276-
if (len >= MAXNAME)
277-
return -1;
273+
strbuf_addch(name, tolower(c));
278274
}
279-
name[len] = 0;
275+
280276
while (c == ' ' || c == '\t')
281277
c = get_next_char();
282278

@@ -288,10 +284,10 @@ static int get_value(config_fn_t fn, void *data, char *name, unsigned int len)
288284
if (!value)
289285
return -1;
290286
}
291-
return fn(name, value, data);
287+
return fn(name->buf, value, data);
292288
}
293289

294-
static int get_extended_base_var(char *name, int baselen, int c)
290+
static int get_extended_base_var(struct strbuf *name, int c)
295291
{
296292
do {
297293
if (c == '\n')
@@ -302,7 +298,7 @@ static int get_extended_base_var(char *name, int baselen, int c)
302298
/* We require the format to be '[base "extension"]' */
303299
if (c != '"')
304300
return -1;
305-
name[baselen++] = '.';
301+
strbuf_addch(name, '.');
306302

307303
for (;;) {
308304
int c = get_next_char();
@@ -315,45 +311,39 @@ static int get_extended_base_var(char *name, int baselen, int c)
315311
if (c == '\n')
316312
goto error_incomplete_line;
317313
}
318-
name[baselen++] = c;
319-
if (baselen > MAXNAME / 2)
320-
return -1;
314+
strbuf_addch(name, c);
321315
}
322316

323317
/* Final ']' */
324318
if (get_next_char() != ']')
325319
return -1;
326-
return baselen;
320+
return 0;
327321
error_incomplete_line:
328322
cf->linenr--;
329323
return -1;
330324
}
331325

332-
static int get_base_var(char *name)
326+
static int get_base_var(struct strbuf *name)
333327
{
334-
int baselen = 0;
335-
336328
for (;;) {
337329
int c = get_next_char();
338330
if (cf->eof)
339331
return -1;
340332
if (c == ']')
341-
return baselen;
333+
return 0;
342334
if (isspace(c))
343-
return get_extended_base_var(name, baselen, c);
335+
return get_extended_base_var(name, c);
344336
if (!iskeychar(c) && c != '.')
345337
return -1;
346-
if (baselen > MAXNAME / 2)
347-
return -1;
348-
name[baselen++] = tolower(c);
338+
strbuf_addch(name, tolower(c));
349339
}
350340
}
351341

352342
static int git_parse_file(config_fn_t fn, void *data)
353343
{
354344
int comment = 0;
355345
int baselen = 0;
356-
char *var = cf->var;
346+
struct strbuf *var = &cf->var;
357347

358348
/* U+FEFF Byte Order Mark in UTF8 */
359349
static const unsigned char *utf8_bom = (unsigned char *) "\xef\xbb\xbf";
@@ -389,17 +379,24 @@ static int git_parse_file(config_fn_t fn, void *data)
389379
continue;
390380
}
391381
if (c == '[') {
392-
baselen = get_base_var(var);
393-
if (baselen <= 0)
382+
/* Reset prior to determining a new stem */
383+
strbuf_reset(var);
384+
if (get_base_var(var) < 0 || var->len < 1)
394385
break;
395-
var[baselen++] = '.';
396-
var[baselen] = 0;
386+
strbuf_addch(var, '.');
387+
baselen = var->len;
397388
continue;
398389
}
399390
if (!isalpha(c))
400391
break;
401-
var[baselen] = tolower(c);
402-
if (get_value(fn, data, var, baselen+1) < 0)
392+
/*
393+
* Truncate the var name back to the section header
394+
* stem prior to grabbing the suffix part of the name
395+
* and the value.
396+
*/
397+
strbuf_setlen(var, baselen);
398+
strbuf_addch(var, tolower(c));
399+
if (get_value(fn, data, var) < 0)
403400
break;
404401
}
405402
die("bad config file line %d in %s", cf->linenr, cf->name);
@@ -899,12 +896,14 @@ int git_config_from_file(config_fn_t fn, const char *filename, void *data)
899896
top.linenr = 1;
900897
top.eof = 0;
901898
strbuf_init(&top.value, 1024);
899+
strbuf_init(&top.var, 1024);
902900
cf = &top;
903901

904902
ret = git_parse_file(fn, data);
905903

906904
/* pop config-file parsing state stack */
907905
strbuf_release(&top.value);
906+
strbuf_release(&top.var);
908907
cf = top.prev;
909908

910909
fclose(f);

0 commit comments

Comments
 (0)