Fix hang on recursive substitution `defines, bug443.
This commit is contained in:
parent
c8e4b1fc84
commit
09c10492ab
3
Changes
3
Changes
|
|
@ -18,6 +18,9 @@ indicates the contributor was also the author of the fix; Thanks!
|
|||
|
||||
**** Fix hang when functions inside begin block. [David Welch]
|
||||
|
||||
**** Fix hang on recursive substitution `defines, bug443. [Alex Solomatnikov]
|
||||
|
||||
|
||||
* Verilator 3.831 2012/01/20
|
||||
|
||||
** Support SystemC 2.3.0 prerelease. This requires setting the new
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
//======================================================================
|
||||
|
||||
class V3PreLex;
|
||||
class V3PreProcImp;
|
||||
|
||||
// Token codes
|
||||
|
|
@ -126,16 +127,23 @@ void yy_delete_buffer( YY_BUFFER_STATE b );
|
|||
class VPreStream {
|
||||
public:
|
||||
FileLine* m_curFilelinep; // Current processing point (see also m_tokFilelinep)
|
||||
V3PreLex* m_lexp; // Lexer, for resource tracking
|
||||
deque<string> m_buffers; // Buffer of characters to process
|
||||
int m_ignNewlines; // Ignore multiline newlines
|
||||
bool m_eof; // "EOF" buffer
|
||||
bool m_file; // Buffer is start of new file
|
||||
int m_termState; // Termination fsm
|
||||
VPreStream(FileLine* fl)
|
||||
: m_curFilelinep(fl), m_ignNewlines(0),
|
||||
VPreStream(FileLine* fl, V3PreLex* lexp)
|
||||
: m_curFilelinep(fl), m_lexp(lexp),
|
||||
m_ignNewlines(0),
|
||||
m_eof(false), m_file(false), m_termState(0) {
|
||||
lexStreamDepthAdd(1);
|
||||
}
|
||||
~VPreStream() {}
|
||||
~VPreStream() {
|
||||
lexStreamDepthAdd(-1);
|
||||
}
|
||||
private:
|
||||
void lexStreamDepthAdd(int delta);
|
||||
};
|
||||
|
||||
//======================================================================
|
||||
|
|
@ -145,6 +153,7 @@ class V3PreLex {
|
|||
public: // Used only by V3PreLex.cpp and V3PreProc.cpp
|
||||
V3PreProcImp* m_preimpp; // Preprocessor lexor belongs to
|
||||
stack<VPreStream*> m_streampStack; // Stack of processing files
|
||||
int m_streamDepth; // Depth of stream processing
|
||||
YY_BUFFER_STATE m_bufferState; // Flex state
|
||||
FileLine* m_tokFilelinep; // Starting position of current token
|
||||
|
||||
|
|
@ -166,6 +175,7 @@ class V3PreLex {
|
|||
// CONSTRUCTORS
|
||||
V3PreLex(V3PreProcImp* preimpp, FileLine* filelinep) {
|
||||
m_preimpp = preimpp;
|
||||
m_streamDepth = 0;
|
||||
m_keepComments = 0;
|
||||
m_keepWhitespace = 1;
|
||||
m_pedantic = false;
|
||||
|
|
@ -207,6 +217,9 @@ class V3PreLex {
|
|||
void dumpSummary();
|
||||
void dumpStack();
|
||||
void unused();
|
||||
// Called by VPreStream
|
||||
void streamDepthAdd(int delta) { m_streamDepth += delta; }
|
||||
int streamDepth() const { return m_streamDepth; }
|
||||
/// Utility
|
||||
static int debug();
|
||||
static void debug(int level);
|
||||
|
|
@ -219,4 +232,6 @@ private:
|
|||
void scanSwitchStream(VPreStream* streamp);
|
||||
};
|
||||
|
||||
inline void VPreStream::lexStreamDepthAdd(int delta) { m_lexp->streamDepthAdd(delta); }
|
||||
|
||||
#endif // Guard
|
||||
|
|
|
|||
|
|
@ -432,7 +432,7 @@ string V3PreLex::endOfStream(bool& againr) {
|
|||
void V3PreLex::initFirstBuffer(FileLine* filelinep) {
|
||||
// Called from constructor to make first buffer
|
||||
// yy_create_buffer also sets yy_fill_buffer=1 so reads from YY_INPUT
|
||||
VPreStream* streamp = new VPreStream(filelinep);
|
||||
VPreStream* streamp = new VPreStream(filelinep, this);
|
||||
streamp->m_eof = true;
|
||||
m_streampStack.push(streamp);
|
||||
//
|
||||
|
|
@ -443,10 +443,16 @@ void V3PreLex::initFirstBuffer(FileLine* filelinep) {
|
|||
|
||||
void V3PreLex::scanNewFile(FileLine* filelinep) {
|
||||
// Called on new open file. scanBytesBack will be called next.
|
||||
VPreStream* streamp = new VPreStream(filelinep);
|
||||
m_tokFilelinep = curFilelinep();
|
||||
streamp->m_file = true;
|
||||
scanSwitchStream(streamp);
|
||||
if (streamDepth() > V3PreProc::DEFINE_RECURSION_LEVEL_MAX) {
|
||||
// The recursive `include in VPreProcImp should trigger first
|
||||
yyerrorf("Recursive `define or other nested inclusion");
|
||||
curStreamp()->m_eof = true; // Fake it to stop recursion
|
||||
} else {
|
||||
VPreStream* streamp = new VPreStream(filelinep, this);
|
||||
m_tokFilelinep = curFilelinep();
|
||||
streamp->m_file = true;
|
||||
scanSwitchStream(streamp);
|
||||
}
|
||||
}
|
||||
|
||||
void V3PreLex::scanBytes(const string& str) {
|
||||
|
|
@ -455,9 +461,16 @@ void V3PreLex::scanBytes(const string& str) {
|
|||
// to take effect immediately, in the middle of the current buffer
|
||||
// Also we don't use scan_bytes that would set yy_fill_buffer
|
||||
// which would force Flex to bypass our YY_INPUT routine.
|
||||
VPreStream* streamp = new VPreStream(curFilelinep());
|
||||
streamp->m_buffers.push_front(str);
|
||||
scanSwitchStream(streamp);
|
||||
if (streamDepth() > V3PreProc::DEFINE_RECURSION_LEVEL_MAX) {
|
||||
// More streams if recursive `define with complex insertion
|
||||
// More buffers mostly if something internal goes funky
|
||||
yyerrorf("Recursive `define or other nested inclusion");
|
||||
curStreamp()->m_eof = true; // Fake it to stop recursion
|
||||
} else {
|
||||
VPreStream* streamp = new VPreStream(curFilelinep(), this);
|
||||
streamp->m_buffers.push_front(str);
|
||||
scanSwitchStream(streamp);
|
||||
}
|
||||
}
|
||||
|
||||
void V3PreLex::scanSwitchStream(VPreStream* streamp) {
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ struct V3PreProcImp : public V3PreProc {
|
|||
typedef std::map<string,V3Define> DefinesMap;
|
||||
typedef V3InFilter::StrList StrList;
|
||||
|
||||
// debug() -> see V3PreShellImp::debug
|
||||
// debug() -> see V3PreShellImp::debug; use --debugi-V3PreShell
|
||||
|
||||
// Defines list
|
||||
DefinesMap m_defines; ///< Map of defines
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@ public:
|
|||
enum MiscConsts {
|
||||
DEFINE_RECURSION_LEVEL_MAX = 1000, // How many `def substitutions before an error
|
||||
INCLUDE_DEPTH_MAX = 500, // How many `includes deep before an error
|
||||
STREAM_DEPTH_LEVEL_MAX = 2000, // How many streams deep (sometimes `def deep) before an error
|
||||
// // Set more than DEFINE_RECURSION_LEVEL_MAX or INCLUDE_DEPTH_MAX
|
||||
NEWLINES_VS_TICKLINE = 20 // Use `line in place of this many newlines
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
#!/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.
|
||||
|
||||
$Self->{vlt} or $Self->skip("Verilator only test");
|
||||
|
||||
compile (
|
||||
v_flags2 => ["--lint-only"],
|
||||
fails=>1,
|
||||
expect=>
|
||||
'%Error: t/t_pp_circdef_bad.v:\d+: Recursive `define or other nested inclusion
|
||||
.*
|
||||
%Error: Exiting due to.*',
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2011 by Wilson Snyder.
|
||||
//
|
||||
// bug445
|
||||
|
||||
`define WIDTH 12
|
||||
`define SEL_NUM_BITS `WIDTH-`SEL_NUM_BITS +: `SEL_NUM_BITS
|
||||
`define SEL_BITS `WIDTH-`SEL_NUM_BITS +: `SEL_NUM_BITS
|
||||
`define ADDR_BITS 0 +: `WIDTH-`SEL_NUM_BITS
|
||||
|
||||
typedef logic [`SEL_NUM_BITS-1:0] d_t;
|
||||
Loading…
Reference in New Issue