aboutsummaryrefslogtreecommitdiffstats
path: root/frontends
diff options
context:
space:
mode:
authorXiretza <xiretza@xiretza.xyz>2021-03-16 16:42:14 +0100
committerZachary Snow <zachary.j.snow@gmail.com>2021-03-18 20:52:36 -0400
commit0c66141ed25b0af229551f9ce8fe844be1e88bf3 (patch)
treef1cf91507dc5fb20ae075f2fd8c28ba7d9d86299 /frontends
parent3a12617ec0713aeb81fbf4beede804545f762a1f (diff)
downloadyosys-0c66141ed25b0af229551f9ce8fe844be1e88bf3.tar.gz
yosys-0c66141ed25b0af229551f9ce8fe844be1e88bf3.tar.bz2
yosys-0c66141ed25b0af229551f9ce8fe844be1e88bf3.zip
verilog: rebuild user_type_stack from globals before parsing file
This was actually a ticking UB bomb: after running the parser, the type maps contain pointers to children of the current AST, which is recursively deleted after the pass has executed. This leaves the pointers in user_type_stack dangling, which just happened to never be a problem due to another bug that causes typedefs from higher-level type maps to never be considered. Rebuilding the type stack from the design's globals ensures the AstNode pointers are valid.
Diffstat (limited to 'frontends')
-rw-r--r--frontends/verilog/verilog_frontend.cc26
1 files changed, 21 insertions, 5 deletions
diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc
index 5907707c8..84ac73e91 100644
--- a/frontends/verilog/verilog_frontend.cc
+++ b/frontends/verilog/verilog_frontend.cc
@@ -61,11 +61,6 @@ static void add_package_types(dict<std::string, AST::AstNode *> &user_types, std
}
}
}
-
- // carry over typedefs from previous files, but allow them to be overridden
- // note that these type maps are currently never reclaimed
- if (user_type_stack.empty() || !user_type_stack.back()->empty())
- user_type_stack.push_back(new UserTypeMap());
}
struct VerilogFrontend : public Frontend {
@@ -487,6 +482,19 @@ struct VerilogFrontend : public Frontend {
// make package typedefs available to parser
add_package_types(pkg_user_types, design->verilog_packages);
+ UserTypeMap *global_types_map = new UserTypeMap();
+ for (auto def : design->verilog_globals) {
+ if (def->type == AST::AST_TYPEDEF) {
+ (*global_types_map)[def->str] = def;
+ }
+ }
+
+ log_assert(user_type_stack.empty());
+ // use previous global typedefs as bottom level of user type stack
+ user_type_stack.push_back(global_types_map);
+ // add a new empty type map to allow overriding existing global definitions
+ user_type_stack.push_back(new UserTypeMap());
+
frontend_verilog_yyset_lineno(1);
frontend_verilog_yyrestart(NULL);
frontend_verilog_yyparse();
@@ -509,6 +517,14 @@ struct VerilogFrontend : public Frontend {
if (!flag_nopp)
delete lexin;
+ // only the previous and new global type maps remain
+ log_assert(user_type_stack.size() == 2);
+ for (auto it : user_type_stack) {
+ // the global typedefs have to remain valid for future invocations, so just drop the map without deleting values
+ delete it;
+ }
+ user_type_stack.clear();
+
delete current_ast;
current_ast = NULL;