From 71fa09a25bc153ded91d366321189c23890222a8 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Fri, 18 Oct 2019 21:30:34 -0400 Subject: [PATCH] Fix bad-syntax crashes, bug1563. --- Changes | 2 +- src/V3PreLex.h | 3 ++- src/V3PreLex.l | 19 +++++++++++-------- src/V3PreProc.cpp | 11 +++++++---- test_regress/t/t_preproc_cmtend_bad.out | 2 ++ test_regress/t/t_preproc_cmtend_bad.pl | 18 ++++++++++++++++++ test_regress/t/t_preproc_cmtend_bad.v | 7 +++++++ test_regress/t/t_preproc_stringend_bad.out | 2 ++ test_regress/t/t_preproc_stringend_bad.pl | 18 ++++++++++++++++++ test_regress/t/t_preproc_stringend_bad.v | 6 ++++++ 10 files changed, 74 insertions(+), 14 deletions(-) create mode 100644 test_regress/t/t_preproc_cmtend_bad.out create mode 100755 test_regress/t/t_preproc_cmtend_bad.pl create mode 100644 test_regress/t/t_preproc_cmtend_bad.v create mode 100644 test_regress/t/t_preproc_stringend_bad.out create mode 100755 test_regress/t/t_preproc_stringend_bad.pl create mode 100644 test_regress/t/t_preproc_stringend_bad.v diff --git a/Changes b/Changes index 7a00339da..5adc0ef28 100644 --- a/Changes +++ b/Changes @@ -18,7 +18,7 @@ The contributors that suggested a given feature are shown in []. Thanks! **** Fix multithreaded yield behavior when no work. [Patrick Stewart] -**** Fix misc bad-syntax crashes, bug1548, bug1550-1553, bug1557-1560. [Eric Rippey] +**** Fix bad-syntax crashes, bug1548, bug1550-1553, bug1557-1560, bug1563. [Eric Rippey] * Verilator 4.020 2019-10-06 diff --git a/src/V3PreLex.h b/src/V3PreLex.h index 26e657e0b..824c3cb4d 100644 --- a/src/V3PreLex.h +++ b/src/V3PreLex.h @@ -38,7 +38,8 @@ class V3PreProcImp; // Token codes // If changing, see V3PreProc.cpp's V3PreProcImp::tokenName() -#define VP_EOF 0 +#define VP_EOF 0 // Must be zero, a.k.a. YY_NULL, a.k.a. yy_terminate(); +#define VP_EOF_ERROR 400 #define VP_INCLUDE 256 #define VP_IFDEF 257 diff --git a/src/V3PreLex.l b/src/V3PreLex.l index 9e6cf51f5..3394d72e5 100644 --- a/src/V3PreLex.l +++ b/src/V3PreLex.l @@ -117,7 +117,7 @@ bom [\357\273\277] /* Pass-through strings */ {quote} { yy_push_state(STRMODE); yymore(); } <> { FL_FWDC; linenoInc(); yyerrorf("EOF in unterminated string"); - yyleng=0; yyterminate(); } + yyleng=0; return VP_EOF_ERROR; } {crnl} { FL_FWDC; linenoInc(); yyerrorf("Unterminated string"); FL_BRK; BEGIN(INITIAL); } {word} { yymore(); } @@ -134,7 +134,7 @@ bom [\357\273\277] /* Stringification */ {tickquote} { FL_FWDC; yy_push_state(STRIFY); return VP_STRIFY; } <> { FL_FWDC; linenoInc(); yyerrorf("EOF in unterminated '\""); - yyleng=0; yyterminate(); } + yyleng=0; return VP_EOF_ERROR; } "`\\`\"" { FL_FWDC; return VP_BACKQUOTE; } {quote} { yy_push_state(STRMODE); yymore(); } {tickquote} { FL_FWDC; yy_pop_state(); return VP_STRIFY; } @@ -152,14 +152,14 @@ bom [\357\273\277] /* Protected blocks */ "`protected" { yy_push_state(PRTMODE); yymore(); } <> { FL_FWDC; linenoInc(); yyerrorf("EOF in `protected"); - yyleng = 0; yyterminate(); } + yyleng = 0; return VP_EOF_ERROR; } {crnl} { FL_FWDC; linenoInc(); return VP_TEXT; } . { yymore(); } "`endprotected" { FL_FWDC; yy_pop_state(); return VP_TEXT; } /* Pass-through include <> filenames */ <> { FL_FWDC; linenoInc(); yyerrorf("EOF in unterminated include filename"); - yyleng = 0; yyterminate(); } + yyleng = 0; return VP_EOF_ERROR; } {crnl} { FL_FWDC; linenoInc(); yyerrorf("Unterminated include filename"); FL_BRK; BEGIN(INITIAL); } [^\>\\] { yymore(); } @@ -222,13 +222,15 @@ bom [\357\273\277] BEGIN(CMTMODE); } {word} { yymore(); } . { yymore(); } -<> { FL_FWDC; yyerrorf("EOF in '/* ... */' block comment\n"); yyleng=0; yyterminate(); } +<> { FL_FWDC; yyerrorf("EOF in '/* ... */' block comment\n"); + yyleng=0; return VP_EOF_ERROR; } /* Define arguments (use of a define) */ "/*" { yy_push_state(CMTMODE); yymore(); } "//"[^\n\r]* { FL_FWDC; return VP_COMMENT; } {drop} { FL_FWDC; FL_BRK; } -<> { FL_FWDC; yyerrorf("EOF in define argument list\n"); yyleng = 0; yyterminate(); } +<> { FL_FWDC; yyerrorf("EOF in define argument list\n"); + yyleng = 0; return VP_EOF_ERROR; } {crnl} { FL_FWDC; linenoInc(); yytext=(char*)"\n"; yyleng=1; return VP_WHITE; } {quote} { yy_push_state(STRMODE); yymore(); } "`\\`\"" { FL_FWDC; appendDefValue(yytext, yyleng); FL_BRK; } /* Literal text */ @@ -273,7 +275,8 @@ bom [\357\273\277] {ws}+ { yymore(); } "*/" { FL_FWDC; yy_pop_state(); return VP_COMMENT; } {crnl} { linenoInc(); yymore(); } -<> { FL_FWDC; yyerrorf("EOF in '/* ... */' block comment\n"); yyleng=0; yyterminate(); } +<> { FL_FWDC; yyerrorf("EOF in '/* ... */' block comment\n"); + yyleng=0; return VP_EOF_ERROR; } {word} { yymore(); } . { yymore(); BEGIN CMTMODE; } /* beginning in comment */ . { yymore(); } @@ -285,7 +288,7 @@ bom [\357\273\277] /* Generics */ {crnl} { FL_FWDC; linenoInc(); yytext=(char*)"\n"; yyleng=1; return VP_WHITE; } -<> { FL_FWDC; yyterminate(); } /* A "normal" EOF */ +<> { FL_FWDC; return VP_EOF; } /* A "normal" EOF */ {symb} { FL_FWDC; return VP_SYMBOL; } {symb}`` { FL_FWDC; yyleng-=2; return VP_SYMBOL_JOIN; } `` { FL_FWDC; yyleng-=2; return VP_JOIN; } diff --git a/src/V3PreProc.cpp b/src/V3PreProc.cpp index 68ba04253..ed236cce6 100644 --- a/src/V3PreProc.cpp +++ b/src/V3PreProc.cpp @@ -230,6 +230,7 @@ public: // METHODS, called from upper level shell void openFile(FileLine* fl, VInFilter* filterp, const string& filename); bool isEof() const { return m_lexp->curStreamp()->m_eof; } + void forceEof() { m_lexp->curStreamp()->m_eof = true; } string getline(); void insertUnreadback(const string& text) { m_lineCmt += text; } void insertUnreadbackAtBol(const string& text); @@ -497,6 +498,7 @@ const char* V3PreProcImp::tokenName(int tok) { case VP_ELSIF : return("ELSIF"); case VP_ENDIF : return("ENDIF"); case VP_EOF : return("EOF"); + case VP_EOF_ERROR : return("EOF_ERROR"); case VP_ERROR : return("ERROR"); case VP_IFDEF : return("IFDEF"); case VP_IFNDEF : return("IFNDEF"); @@ -885,12 +887,13 @@ int V3PreProcImp::getRawToken() { // Snarf next token from the file m_lexp->curFilelinep()->startToken(); int tok = m_lexp->lex(); - if (debug()>=5) debugToken(tok, "RAW"); - // A EOF on an include, so we can print `line and detect mis-matched "s - if (tok==VP_EOF) { - goto next_tok; // find the EOF, after adding needed lines + if (tok==VP_EOF || tok==VP_EOF_ERROR) { + // An error might be in an unexpected point, so stop parsing + if (tok==VP_EOF_ERROR) forceEof(); + // A EOF on an include, stream will find the EOF, after adding needed `lines + goto next_tok; } if (yyourleng()) m_rawAtBol = (yyourtext()[yyourleng()-1]=='\n'); diff --git a/test_regress/t/t_preproc_cmtend_bad.out b/test_regress/t/t_preproc_cmtend_bad.out new file mode 100644 index 000000000..9a57b89a5 --- /dev/null +++ b/test_regress/t/t_preproc_cmtend_bad.out @@ -0,0 +1,2 @@ +%Error: t/t_preproc_cmtend_bad.v:9: EOF in '/* ... */' block comment +%Error: Exiting due to diff --git a/test_regress/t/t_preproc_cmtend_bad.pl b/test_regress/t/t_preproc_cmtend_bad.pl new file mode 100755 index 000000000..b09f43e8b --- /dev/null +++ b/test_regress/t/t_preproc_cmtend_bad.pl @@ -0,0 +1,18 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you can +# redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. + +scenarios(linter => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_preproc_cmtend_bad.v b/test_regress/t/t_preproc_cmtend_bad.v new file mode 100644 index 000000000..165be9aaf --- /dev/null +++ b/test_regress/t/t_preproc_cmtend_bad.v @@ -0,0 +1,7 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2019 by Wilson Snyder. + +/*Blah +blah diff --git a/test_regress/t/t_preproc_stringend_bad.out b/test_regress/t/t_preproc_stringend_bad.out new file mode 100644 index 000000000..a0c3c04b1 --- /dev/null +++ b/test_regress/t/t_preproc_stringend_bad.out @@ -0,0 +1,2 @@ +%Error: t/t_preproc_stringend_bad.v:7: Unterminated string +%Error: Exiting due to diff --git a/test_regress/t/t_preproc_stringend_bad.pl b/test_regress/t/t_preproc_stringend_bad.pl new file mode 100755 index 000000000..b09f43e8b --- /dev/null +++ b/test_regress/t/t_preproc_stringend_bad.pl @@ -0,0 +1,18 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you can +# redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. + +scenarios(linter => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_preproc_stringend_bad.v b/test_regress/t/t_preproc_stringend_bad.v new file mode 100644 index 000000000..7dfbdde6b --- /dev/null +++ b/test_regress/t/t_preproc_stringend_bad.v @@ -0,0 +1,6 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2019 by Wilson Snyder. + +"Blah