Hi,
While generating big prefixlists macros with bgpq3 (big like as2914:as-europe-v6
for example), OpenBGPd cannot load the config file (error "string too long").
This diff implements a dynamic buffer to overcome this limitation.
Index: parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/parse.y,v
retrieving revision 1.331
diff -u -p -r1.331 parse.y
--- parse.y 27 Aug 2018 19:32:37 -0000 1.331
+++ parse.y 4 Sep 2018 18:13:48 -0000
@@ -2746,13 +2746,22 @@ findeol(void)
return (ERROR);
}
+#define READBUFFERSIZE 1024
+
int
yylex(void)
{
- u_char buf[8096];
+ u_char *buf = NULL;
u_char *p, *val;
int quotec, next, c;
int token;
+ u_int32_t bufsize = READBUFFERSIZE;
+
+ buf = malloc(bufsize);
+ if (buf == NULL) {
+ yyerror("malloc failed");
+ return (findeol());
+ }
top:
p = buf;
@@ -2765,12 +2774,19 @@ top:
; /* nothing */
if (c == '$' && !expanding) {
while (1) {
- if ((c = lgetc(0)) == EOF)
+ if ((c = lgetc(0)) == EOF) {
+ free(buf);
return (0);
+ }
- if (p + 1 >= buf + sizeof(buf) - 1) {
- yyerror("string too long");
- return (findeol());
+ if (p + 1 >= buf + bufsize - 1) {
+ bufsize += READBUFFERSIZE;
+ buf = realloc(buf, bufsize);
+ if (buf == NULL) {
+ yyerror("realloc failed");
+ return (findeol());
+ }
+ p = buf + bufsize - READBUFFERSIZE - 2;
}
if (isalnum(c) || c == '_') {
*p++ = c;
@@ -2783,6 +2799,7 @@ top:
val = symget(buf);
if (val == NULL) {
yyerror("macro '%s' not defined", buf);
+ free(buf);
return (findeol());
}
p = val + strlen(val) - 1;
@@ -2800,14 +2817,18 @@ top:
case '"':
quotec = c;
while (1) {
- if ((c = lgetc(quotec)) == EOF)
+ if ((c = lgetc(quotec)) == EOF) {
+ free(buf);
return (0);
+ }
if (c == '\n') {
file->lineno++;
continue;
} else if (c == '\\') {
- if ((next = lgetc(quotec)) == EOF)
+ if ((next = lgetc(quotec)) == EOF) {
+ free(buf);
return (0);
+ }
if (next == quotec || c == ' ' || c == '\t')
c = next;
else if (next == '\n') {
@@ -2820,36 +2841,52 @@ top:
break;
} else if (c == '\0') {
yyerror("syntax error");
+ free(buf);
return (findeol());
}
- if (p + 1 >= buf + sizeof(buf) - 1) {
- yyerror("string too long");
- return (findeol());
+ if (p + 1 >= buf + bufsize - 1) {
+ bufsize += READBUFFERSIZE;
+ buf = realloc(buf, bufsize);
+ if (buf == NULL) {
+ yyerror("realloc failed");
+ return (findeol());
+ }
+ p = buf + bufsize - READBUFFERSIZE - 2;
}
*p++ = c;
}
yylval.v.string = strdup(buf);
- if (yylval.v.string == NULL)
+ if (yylval.v.string == NULL) {
+ free(buf);
fatal("yylex: strdup");
+ }
return (STRING);
case '!':
next = lgetc(0);
- if (next == '=')
+ if (next == '=') {
+ free(buf);
return (NE);
+ }
lungetc(next);
break;
case '<':
next = lgetc(0);
- if (next == '=')
+ if (next == '=') {
+ free(buf);
return (LE);
+ }
lungetc(next);
break;
case '>':
next = lgetc(0);
- if (next == '<')
+ if (next == '<') {
+ free(buf);
return (XRANGE);
- else if (next == '=')
+ }
+ else if (next == '=') {
+ free(buf);
return (GE);
+ }
lungetc(next);
break;
}
@@ -2860,9 +2897,14 @@ top:
if (c == '-' || isdigit(c)) {
do {
*p++ = c;
- if ((unsigned)(p-buf) >= sizeof(buf)) {
- yyerror("string too long");
- return (findeol());
+ if ((unsigned)(p-buf) >= bufsize) {
+ bufsize += READBUFFERSIZE;
+ buf = realloc(buf, bufsize);
+ if (buf == NULL) {
+ yyerror("realloc failed");
+ return (findeol());
+ }
+ p = buf + bufsize - READBUFFERSIZE;
}
} while ((c = lgetc(0)) != EOF && isdigit(c));
lungetc(c);
@@ -2877,16 +2919,20 @@ top:
if (errstr) {
yyerror("\"%s\" invalid number: %s",
buf, errstr);
+ free(buf);
return (findeol());
}
+ free(buf);
return (NUMBER);
} else {
nodigits:
while (p > buf + 1)
lungetc(*--p);
c = *--p;
- if (c == '-')
+ if (c == '-') {
+ free(buf);
return (c);
+ }
}
}
@@ -2899,22 +2945,31 @@ nodigits:
if (isalnum(c) || c == ':' || c == '_' || c == '*') {
do {
*p++ = c;
- if ((unsigned)(p-buf) >= sizeof(buf)) {
- yyerror("string too long");
- return (findeol());
+ if ((unsigned)(p-buf) >= bufsize) {
+ bufsize += READBUFFERSIZE;
+ buf = realloc(buf, bufsize);
+ if (buf == NULL) {
+ yyerror("realloc failed");
+ return (findeol());
+ }
+ p = buf + bufsize - READBUFFERSIZE;
}
} while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
lungetc(c);
*p = '\0';
if ((token = lookup(buf)) == STRING)
- if ((yylval.v.string = strdup(buf)) == NULL)
+ if ((yylval.v.string = strdup(buf)) == NULL) {
+ free(buf);
fatal("yylex: strdup");
+ }
+ free(buf);
return (token);
}
if (c == '\n') {
yylval.lineno = file->lineno;
file->lineno++;
}
+ free(buf);
if (c == EOF)
return (0);
return (c);