From a11e0726bba8bfc1f5587f8044a2ac2fd7fe638c Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Sun, 12 May 2024 23:29:48 +0800 Subject: [PATCH] :fire: add check for imported files' quantity --- makefile | 2 +- src/main.cpp | 10 +++++----- src/nasal_codegen.cpp | 36 ++++++++++++++++++++++-------------- src/nasal_codegen.h | 14 +++++++------- src/nasal_dbg.cpp | 4 ++-- src/nasal_dbg.h | 2 +- src/nasal_import.cpp | 9 ++++++++- src/repl.cpp | 12 ++++++------ 8 files changed, 52 insertions(+), 37 deletions(-) diff --git a/makefile b/makefile index aae7741..7bbc56c 100644 --- a/makefile +++ b/makefile @@ -6,7 +6,7 @@ endif ifeq ($(OS), Darwin) CXXFLAGS = -std=$(STD) -c -O3 -fPIC -mmacosx-version-min=10.15 -I src else - CXXFLAGS = -std=$(STD) -c -O3 -fPIC -I src -Wconversion -Wno-float-conversion + CXXFLAGS = -std=$(STD) -c -O3 -fPIC -I src endif NASAL_HEADER = \ diff --git a/src/main.cpp b/src/main.cpp index 42d12f0..422cd27 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -95,7 +95,7 @@ std::ostream& logo(std::ostream& out) { } std::ostream& version(std::ostream& out) { - std::srand(static_cast(std::time(nullptr))); + std::srand(static_cast(std::time(nullptr))); f64 num = 0; for(u32 i = 0; i<5; ++i) { @@ -152,7 +152,7 @@ void execute(const std::string& file, } // optimizer does simple optimization on ast - auto opt = std::unique_ptr(new nasal::optimizer); + auto opt = std::make_unique(); opt->do_optimization(parse.tree()); if (cmd&VM_AST) { nasal::ast_dumper().dump(parse.tree()); @@ -170,10 +170,10 @@ void execute(const std::string& file, // run const auto start = clk::now(); if (cmd&VM_DEBUG) { - auto debugger = std::unique_ptr(new nasal::dbg); + auto debugger = std::make_unique(); debugger->run(gen, ld, argv, cmd&VM_PROFILE, cmd&VM_PROF_ALL); } else if (cmd&VM_TIME || cmd&VM_EXEC) { - auto runtime = std::unique_ptr(new nasal::vm); + auto runtime = std::make_unique(); runtime->set_detail_report_info(cmd&VM_DETAIL); runtime->set_limit_mode_flag(cmd&VM_LIMIT); runtime->run(gen, ld, argv); @@ -202,7 +202,7 @@ i32 main(i32 argc, const char* argv[]) { } else if (s=="-v" || s=="--version") { std::clog << version; } else if (s=="-r" || s=="--repl") { - auto repl = std::unique_ptr(new nasal::repl::repl); + auto repl = std::make_unique(); repl->execute(); } else if (s[0]!='-') { execute(s, {}, VM_EXEC); diff --git a/src/nasal_codegen.cpp b/src/nasal_codegen.cpp index 81ec3ae..ad94ff5 100644 --- a/src/nasal_codegen.cpp +++ b/src/nasal_codegen.cpp @@ -87,7 +87,7 @@ void codegen::regist_string(const std::string& str) { } void codegen::find_symbol(code_block* node) { - auto finder = std::unique_ptr(new symbol_finder); + auto finder = std::make_unique(); for(const auto& i : finder->do_find(node)) { // check if symbol conflicts with native function name if (native_function_mapper.count(i.name)) { @@ -95,11 +95,11 @@ void codegen::find_symbol(code_block* node) { continue; } // create new namespace with checking existence of location file - if (!experimental_namespace.count(i.location.file)) { - experimental_namespace[i.location.file] = {}; + if (!nasal_namespace.count(i.location.file)) { + nasal_namespace[i.location.file] = {}; } // if in global scope, load global symbol into this namespace - auto& scope = experimental_namespace.at(i.location.file); + auto& scope = nasal_namespace.at(i.location.file); if (local.empty() && !scope.count(i.name)) { scope.insert(i.name); } @@ -126,26 +126,30 @@ void codegen::regist_symbol(const std::string& name) { local.back()[name] = index; } -i32 codegen::local_symbol_find(const std::string& name) { +i64 codegen::local_symbol_find(const std::string& name) { if (local.empty()) { return -1; } return local.back().count(name)? local.back().at(name):-1; } -i32 codegen::global_symbol_find(const std::string& name) { +i64 codegen::global_symbol_find(const std::string& name) { return global.count(name)? global.at(name):-1; } -i32 codegen::upvalue_symbol_find(const std::string& name) { +i64 codegen::upvalue_symbol_find(const std::string& name) { // 32768 level 65536 upvalues - i32 index = -1; + // may cause some errors if local scope depth is too deep or + // local scope's symbol list size is greater than 65536, + // but we check the local size in codegen::func_gen + i64 index = -1; usize size = local.size(); if (size<=1) { return -1; } + auto iter = local.begin(); - for(u32 i = 0; icount(name)) { index = ((i<<16)|(*iter).at(name)); } @@ -301,10 +305,14 @@ void codegen::func_gen(function* node) { block_gen(block); in_foreach_loop_level.pop_back(); + // we must check the local scope symbol list size + // the local scope should not cause stack overflow + // and should not greater than upvalue's max size(65536) code[lsize].num = local.back().size(); - if (local.back().size()>=STACK_DEPTH) { + if (local.back().size()>=STACK_DEPTH || local.back().size()>=UINT16_MAX) { die("too many local variants: " + - std::to_string(local.back().size()), block->get_location() + std::to_string(local.back().size()), + block->get_location() ); } local.pop_back(); @@ -350,7 +358,7 @@ void codegen::call_identifier(identifier* node) { return; } - i32 index; + i64 index; if ((index = local_symbol_find(name))>=0) { emit(op_calll, index, node->get_location()); return; @@ -470,7 +478,7 @@ void codegen::mcall_identifier(identifier* node) { return; } - i32 index; + i64 index; if ((index = local_symbol_find(name))>=0) { emit(op_mcalll, index, node->get_location()); return; @@ -1428,7 +1436,7 @@ void codegen::print(std::ostream& out) { } void codegen::symbol_dump(std::ostream& out) const { - for(const auto& domain : experimental_namespace) { + for(const auto& domain : nasal_namespace) { out << "<" << domain.first << ">\n"; for(const auto& i : domain.second) { out << " 0x" << std::setw(4) << std::setfill('0'); diff --git a/src/nasal_codegen.h b/src/nasal_codegen.h index 2b3e817..e171f83 100644 --- a/src/nasal_codegen.h +++ b/src/nasal_codegen.h @@ -89,7 +89,10 @@ private: // symbol table // global : max STACK_DEPTH-1 values std::unordered_map global; - std::unordered_map> experimental_namespace; + + // nasal namespace + // stores all global symbols of each file + std::unordered_map> nasal_namespace; // local : max 32768 upvalues 65536 values // but in fact local scope also has less than STACK_DEPTH value @@ -105,9 +108,9 @@ private: void regist_string(const std::string&); void find_symbol(code_block*); void regist_symbol(const std::string&); - i32 local_symbol_find(const std::string&); - i32 global_symbol_find(const std::string&); - i32 upvalue_symbol_find(const std::string&); + i64 local_symbol_find(const std::string&); + i64 global_symbol_find(const std::string&); + i64 upvalue_symbol_find(const std::string&); void emit(u8, u64, const span&); @@ -157,9 +160,6 @@ public: const auto& natives() const {return native_function;} const auto& codes() const {return code;} const auto& globals() const {return global;} - const auto& get_experimental_namespace() const { - return experimental_namespace; - } public: codegen() = default; diff --git a/src/nasal_dbg.cpp b/src/nasal_dbg.cpp index c835817..a1afd3d 100644 --- a/src/nasal_dbg.cpp +++ b/src/nasal_dbg.cpp @@ -113,7 +113,7 @@ u16 dbg::file_index(const std::string& filename) const { return i; } } - return 65535; + return UINT16_MAX; } void dbg::err() { @@ -221,7 +221,7 @@ void dbg::interact() { } else if (res.size()==3 && get_cmd_type(res[0])==cmd_kind::cmd_break_point) { break_file_index = file_index(res[1]); - if (break_file_index==65535) { + if (break_file_index==UINT16_MAX) { std::clog << "cannot find file named `" << res[1] << "`\n"; continue; } diff --git a/src/nasal_dbg.h b/src/nasal_dbg.h index 13c392e..2aa1b0c 100644 --- a/src/nasal_dbg.h +++ b/src/nasal_dbg.h @@ -142,7 +142,7 @@ private: bool next; usize fsize; u16 break_file_index; - u32 break_line; + u64 break_line; error src; private: diff --git a/src/nasal_import.cpp b/src/nasal_import.cpp index 123f956..9d94777 100644 --- a/src/nasal_import.cpp +++ b/src/nasal_import.cpp @@ -316,7 +316,7 @@ std::string linker::generate_module_name(const std::string& file_path) { } return_expr* linker::generate_module_return(code_block* block) { - auto finder = std::unique_ptr(new symbol_finder); + auto finder = std::make_unique(); auto result = new return_expr(block->get_location()); auto value = new hash_expr(block->get_location()); result->set_value(value); @@ -406,6 +406,13 @@ const error& linker::link(parse& parse, bool spath = false) { merge_tree(library, parse.tree()); // swap tree root, and delete old root delete parse.swap(library); + + if (imported_files.size()>=UINT16_MAX) { + err.err("link", + "too many imported files: " + + std::to_string(imported_files.size()) + ); + } return err; } diff --git a/src/repl.cpp b/src/repl.cpp index 1883f6d..e0118c5 100644 --- a/src/repl.cpp +++ b/src/repl.cpp @@ -37,7 +37,7 @@ void repl::update_temp_file() { bool repl::check_need_more_input() { while(true) { update_temp_file(); - auto nasal_lexer = std::unique_ptr(new lexer); + auto nasal_lexer = std::make_unique(); if (nasal_lexer->scan("").geterr()) { return false; } @@ -77,11 +77,11 @@ void repl::help() { } bool repl::run() { - auto nasal_lexer = std::unique_ptr(new lexer); - auto nasal_parser = std::unique_ptr(new parse); - auto nasal_linker = std::unique_ptr(new linker); - auto nasal_opt = std::unique_ptr(new optimizer); - auto nasal_codegen = std::unique_ptr(new codegen); + auto nasal_lexer = std::make_unique(); + auto nasal_parser = std::make_unique(); + auto nasal_linker = std::make_unique(); + auto nasal_opt = std::make_unique(); + auto nasal_codegen = std::make_unique(); update_temp_file(); if (nasal_lexer->scan("").geterr()) {