summaryrefslogtreecommitdiff
path: root/scanner.l
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2018-10-27 15:16:51 -0700
committerGuy Harris <guy@alum.mit.edu>2018-10-27 15:16:51 -0700
commite8767c3bc6894d5b3778e3d043762037aa70b3ba (patch)
tree9f6f47c204c0c5e757e5f6f77ca0d747a4f2b54f /scanner.l
parent849ca429fa7c58aa5e7b99cfc480833796addc6a (diff)
downloadlibpcap-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.l27
1 files changed, 11 insertions, 16 deletions
diff --git a/scanner.l b/scanner.l
index e9565aa6..effcf815 100644
--- a/scanner.l
+++ b/scanner.l
@@ -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; }
%%
/*