From e13e669d7aee0f455953926b6096d96e4b028ae3 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Fri, 1 Apr 2022 16:10:50 -0700 Subject: [PROPOSED 2/2] Simplify field memory allocation in zic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * zic.c (MAX_FIELDS): New macro. (infile): Allocate the fields array on the stack, since it’s small. That way there’s no need to free it explicitly later. (getfields): New args ARRAY and ARRAYELTS, so that there’s no need to allocate an array. Return number of fields found. Report an error if there are too many fields. --- zic.c | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/zic.c b/zic.c index 50c4675..6dff1ea 100644 --- a/zic.c +++ b/zic.c @@ -150,7 +150,7 @@ static void leapadd(zic_t, int, int); static void adjleap(void); static void associate(void); static void dolink(const char *, const char *, bool); -static char ** getfields(char * buf); +static int getfields(char *, char **, int); static zic_t gethms(const char * string, const char * errstring); static zic_t getsave(char *, bool *); static void inexpires(char **, int); @@ -286,6 +286,9 @@ static int unspecifiedtype; /* Expires lines are like Leap lines, except without CORR and ROLL fields. */ #define EXPIRES_FIELDS 5 +/* The maximum number of fields on any of the above lines. */ +#define MAX_FIELDS RULE_FIELDS + /* ** Year synonyms. */ @@ -1347,9 +1350,7 @@ static void infile(const char *name) { register FILE * fp; - register char ** fields; register const struct lookup * lp; - register int nfields; register bool wantcont; register lineno num; @@ -1367,19 +1368,14 @@ infile(const char *name) for (num = 1; ; ++num) { ptrdiff_t linelen; char buf[_POSIX2_LINE_MAX]; + int nfields; + char *fields[MAX_FIELDS]; eat(name, num); linelen = inputline(fp, buf, sizeof buf); if (linelen < 0) break; - fields = getfields(buf); - nfields = 0; - while (fields[nfields] != NULL) { - static char nada; - - if (strcmp(fields[nfields], "-") == 0) - fields[nfields] = &nada; - ++nfields; - } + nfields = getfields(buf, fields, + sizeof fields / sizeof *fields); if (nfields == 0) { /* nothing to do */ } else if (wantcont) { @@ -1413,7 +1409,6 @@ infile(const char *name) default: UNREACHABLE(); } } - free(fields); } close_file(fp, NULL, filename, NULL); if (wantcont) @@ -3378,23 +3373,20 @@ byword(const char *word, const struct lookup *table) return foundlp; } -static char ** -getfields(register char *cp) +static int +getfields(char *cp, char **array, int arrayelts) { register char * dp; - register char ** array; register int nsubs; - if (cp == NULL) - return NULL; - array = emalloc(size_product(strlen(cp) + 1, sizeof *array)); nsubs = 0; for ( ; ; ) { + char *dstart; while (is_space(*cp)) ++cp; if (*cp == '\0' || *cp == '#') break; - array[nsubs++] = dp = cp; + dstart = dp = cp; do { if ((*dp = *cp++) != '"') ++dp; @@ -3409,9 +3401,13 @@ getfields(register char *cp) if (is_space(*cp)) ++cp; *dp = '\0'; + if (nsubs == arrayelts) { + error(_("Too many input fields")); + exit(EXIT_FAILURE); + } + array[nsubs++] = dstart + (*dstart == '-' && dp == dstart + 1); } - array[nsubs] = NULL; - return array; + return nsubs; } static _Noreturn void -- 2.35.1