diff options
author | Guy Harris <guy@alum.mit.edu> | 2018-10-27 15:16:51 -0700 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2018-10-27 15:16:51 -0700 |
commit | e8767c3bc6894d5b3778e3d043762037aa70b3ba (patch) | |
tree | 9f6f47c204c0c5e757e5f6f77ca0d747a4f2b54f /scanner.l | |
parent | 849ca429fa7c58aa5e7b99cfc480833796addc6a (diff) | |
download | libpcap-e8767c3bc6894d5b3778e3d043762037aa70b3ba.tar.gz |
Don't call setjmp in code we didn't write.
Using setjmp() in a routine requires that anything whose value needs
*not* to be restored to its value when setjmp() was called in a
longjmp() be declare "volatile".
We can't force Bison or Berkeley YACC to do that with variables in the
parser function, so we can't safely do a setjmp() in the parser
function. *Some* compilers might recognize setjmp() and automatically
do that, either silently or with a warning, but that's not guaranteed by
the C language specification.
This could cause a problem if it trashes the value of local variables
storing pointers to the parser's pushdown stack, if they're assumed to
point to the *current* stack at the time the stack is freed at the end
of the parser function.
Instead, use setjmp/longjmp only inside functions defined in gencode.c;
have all functions called by the parser do a setjmp and, if it returns
1, return a null pointer, and have all those calls check the return
value and, if it's null, do a YYABORT.
Add a bpf_set_error() routine, for use *outside* gencode.c, which just
sets the error string. In the parser, do a YYABORT after calling it;
in the lexical analyzer, return a token even for errors, but make sure
the token will cause the parse to stop.
Credit to OSS-Fuzz for possibly finding this issue (it may be what's
causing crashes in some tests).
Diffstat (limited to 'scanner.l')
-rw-r--r-- | scanner.l | 27 |
1 files changed, 11 insertions, 16 deletions
@@ -311,13 +311,7 @@ mask return NETMASK; port return PORT; portrange return PORTRANGE; proto return PROTO; -protochain { -#ifdef NO_PROTOCHAIN - bpf_error(yyextra, "%s not supported", yytext); -#else - return PROTOCHAIN; -#endif - } +protochain return PROTOCHAIN; gateway return GATEWAY; @@ -408,17 +402,20 @@ ${B} { yylval->s = sdup(yyextra, yytext); return AID; } memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET6; hints.ai_flags = AI_NUMERICHOST; - if (getaddrinfo(yytext, NULL, &hints, &res)) - bpf_error(yyextra, "bogus IPv6 address %s", yytext); - else { + if (getaddrinfo(yytext, NULL, &hints, &res)) { + bpf_set_error(yyextra, "bogus IPv6 address %s", yytext); + yylval->s = NULL; + } else { freeaddrinfo(res); - yylval->s = sdup(yyextra, (char *)yytext); return HID6; + yylval->s = sdup(yyextra, (char *)yytext); } #else - bpf_error(yyextra, "IPv6 address %s not supported", yytext); + bpf_set_error(yyextra, "IPv6 address %s not supported", yytext); + yylval->s = NULL; #endif /*INET6*/ + return HID6; } -{B}:+({B}:+)+ { bpf_error(yyextra, "bogus ethernet address %s", yytext); } +{B}:+({B}:+)+ { bpf_set_error(yyextra, "bogus ethernet address %s", yytext); yylval->s = NULL; return EID; } icmptype { yylval->i = 0; return NUM; } icmpcode { yylval->i = 1; return NUM; } icmp-echoreply { yylval->i = 0; return NUM; } @@ -478,9 +475,7 @@ tcp-cwr { yylval->i = 0x80; return NUM; } [A-Za-z0-9]([-_.A-Za-z0-9]*[.A-Za-z0-9])? { yylval->s = sdup(yyextra, (char *)yytext); return ID; } "\\"[^ !()\n\t]+ { yylval->s = sdup(yyextra, (char *)yytext + 1); return ID; } -[^ \[\]\t\n\-_.A-Za-z0-9!<>()&|=]+ { - bpf_error(yyextra, "illegal token: %s", yytext); } -. { bpf_error(yyextra, "illegal char '%c'", *yytext); } +. { return LEX_ERROR; } %% /* |