From: Xiretza Date: Tue, 16 Mar 2021 15:42:14 +0000 (+0100) Subject: verilog: rebuild user_type_stack from globals before parsing file X-Git-Tag: yosys-0.10~240 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=0c66141ed25b0af229551f9ce8fe844be1e88bf3;p=yosys.git 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. --- 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 &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;