On Tue, Sep 04, 2018 at 08:15:23PM +0200, Denis Fondras wrote:
> 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.

I would not go down this road. People should not use macros for massive
prefix lists or similar things. Instead prefix-sets should be used. There
are no such limitations with them and they will soon (as n2k18 is
aproaching) get better.

-- 
:wq Claudio

> 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);
> 
> 

Reply via email to