add limited execution mode

This commit is contained in:
ValKmjolnir 2024-02-21 19:55:46 +08:00
parent 38c6fe2c5c
commit b3e6b5784a
8 changed files with 64 additions and 8 deletions

View File

@ -30,6 +30,7 @@ const u32 VM_SYMINFO = 1<<7;
const u32 VM_PROFILE = 1<<8;
const u32 VM_PROF_ALL = 1<<9;
const u32 VM_REF_FILE = 1<<10;
const u32 VM_LIMIT = 1<<11;
std::ostream& help(std::ostream& out) {
out
@ -59,6 +60,7 @@ std::ostream& help(std::ostream& out) {
<< " --prof | show profiling result, available in debug mode.\n"
<< " --prof-all | show profiling result of all files,"
<< "available under debug mode.\n"
<< " --limit | use limited execution mode."
<< "file:\n"
<< " <filename> | execute file.\n"
<< "argv:\n"
@ -155,7 +157,7 @@ void execute(
}
// code generator gets parser's ast and import file list to generate code
gen.compile(parse, ld, false).chkerr();
gen.compile(parse, ld, false, cmd&VM_LIMIT).chkerr();
if (cmd&VM_CODE) {
gen.print(std::cout);
}
@ -171,6 +173,7 @@ void execute(
} else if (cmd&VM_TIME || cmd&VM_EXEC) {
auto runtime = std::unique_ptr<nasal::vm>(new nasal::vm);
runtime->set_detail_report_info(cmd&VM_DETAIL);
runtime->set_limit_mode_flag(cmd&VM_LIMIT);
runtime->run(gen, ld, argv);
}
@ -227,7 +230,8 @@ i32 main(i32 argc, const char* argv[]) {
{"--prof", VM_PROFILE},
{"--prof-all", VM_PROF_ALL},
{"-f", VM_REF_FILE},
{"--ref-file", VM_REF_FILE}
{"--ref-file", VM_REF_FILE},
{"--limit", VM_LIMIT|VM_EXEC}
};
u32 cmd = 0;
std::string filename = "";

View File

@ -3,6 +3,13 @@
namespace nasal {
var builtin_unsafe(context* ctx, gc* ngc) {
return nas_err(
"unsafe_redirect",
"you are using unsafe system api under limited mode!"
);
}
var builtin_print(context* ctx, gc* ngc) {
for(auto& i : ctx->localr[1].vec().elems) {
std::cout << i;

View File

@ -29,6 +29,7 @@
namespace nasal {
var builtin_unsafe(context*, gc*);
var builtin_print(context*, gc*);
var builtin_println(context*, gc*);
var builtin_exit(context*, gc*);

View File

@ -11,12 +11,18 @@ void codegen::init_file_map(const std::vector<std::string>& file_list) {
void codegen::load_native_function_table(nasal_builtin_table* table) {
for(usize i = 0; table[i].func; ++i) {
// check confliction
if (native_function_mapper.count(table[i].name)) {
err.err("code", "\"" + std::string(table[i].name) + "\" conflicts.");
continue;
}
if (flag_limited_mode && unsafe_system_api.count(table[i].name)) {
native_function.push_back({"__unsafe_redirect", builtin_unsafe});
} else {
native_function.push_back(table[i]);
}
auto index = native_function_mapper.size();
// insert into mapper
native_function_mapper[table[i].name] = index;
}
}
@ -1302,10 +1308,14 @@ void codegen::ret_gen(return_expr* node) {
emit(op_ret, 0, node->get_location());
}
const error& codegen::compile(parse& parse, linker& import, bool repl_flag) {
const error& codegen::compile(parse& parse,
linker& import,
bool repl_flag,
bool limit_mode) {
need_repl_output = repl_flag;
flag_limited_mode = limit_mode;
init_native_function();
init_file_map(import.get_file_list());
need_repl_output = repl_flag;
in_foreach_loop_level.push_back(0);

View File

@ -37,6 +37,24 @@ private:
// repl output flag, will generate op_repl to output stack top value if true
bool need_repl_output;
// limit mode flag
bool flag_limited_mode;
const std::unordered_set<std::string> unsafe_system_api = {
// builtin
"__system", "__input",
// io
"__fout", "__open", "__write", "__stat"
// bits
"__fld", "__sfld", "__setfld",
"__buf",
// fg
"__logprint",
// dylib
"__dlopen", "__dlclose", "__dlcallv", "__dlcall",
// unix
"__pipe", "__fork", "__waitpid", "__chdir",
"__environ", "__getcwd", "__getenv"
};
// file mapper for file -> index
std::unordered_map<std::string, usize> file_map;
@ -141,7 +159,7 @@ public:
public:
codegen() = default;
const error& compile(parse&, linker&, bool);
const error& compile(parse&, linker&, bool, bool);
void print(std::ostream&);
void symbol_dump(std::ostream&) const;
};

View File

@ -188,6 +188,7 @@ code_block* linker::import_regular_file(
check_exist_or_record_file(filename);
module_load_stack.push_back(filename);
// avoid stack overflow
if (module_load_stack.size()>MAX_RECURSION_DEPTH) {
err.err("link",
node->get_location(),
@ -258,6 +259,7 @@ code_block* linker::import_nasal_lib() {
}
std::string linker::generate_module_name(const std::string& file_path) {
// import("...") may trigger this error module name
auto error_name = "module@[" + file_path + "]";
if (!file_path.length()) {
return error_name;
@ -332,13 +334,19 @@ return_expr* linker::generate_module_return(code_block* block) {
}
definition_expr* linker::generate_module_definition(code_block* block) {
// generate ast node like this:
// var {module_name} = (func() {
// ... # module itself
// })();
auto def = new definition_expr(block->get_location());
def->set_identifier(new identifier(
block->get_location(),
generate_module_name(block->get_location().file)
));
// (func() {...})();
auto call = new call_expr(block->get_location());
// func() {...}
auto func = new function(block->get_location());
func->set_code_block(block);
func->get_code_block()->add_expression(generate_module_return(block));
@ -392,8 +400,11 @@ const error& linker::link(parse& parse, bool spath = false) {
// then generate a new ast and return to import_ast
// dfs load file
auto library = import_nasal_lib();
// load used modules of this file
load(parse.tree(), this_file);
// then insert the whole tree into library tree root
merge_tree(library, parse.tree());
// swap tree root, and delete old root
delete parse.swap(library);
return err;
}

View File

@ -45,6 +45,9 @@ protected:
bool first_exec_flag = true;
bool allow_repl_output = false;
/* limited mode, will not load unsafe system api if switch on */
bool flag_limited_mode = false;
/* vm initializing function */
void init(
const std::vector<std::string>&,
@ -192,6 +195,8 @@ public:
void set_repl_mode_flag(bool flag) {is_repl_mode = flag;}
/* set repl output flag */
void set_allow_repl_output_flag(bool flag) {allow_repl_output = flag;}
/* set limit mode flag */
void set_limit_mode_flag(bool flag) {flag_limited_mode = flag;}
};
inline bool vm::cond(var& val) {

View File

@ -97,7 +97,7 @@ bool repl::run() {
}
nasal_opt->do_optimization(nasal_parser->tree());
if (nasal_codegen->compile(*nasal_parser, *nasal_linker, true).geterr()) {
if (nasal_codegen->compile(*nasal_parser, *nasal_linker, true, false).geterr()) {
return false;
}