From 8932c515c9b5173ecc045164b970ae03bb4b50c8 Mon Sep 17 00:00:00 2001 From: Aleksandr Kirsanov Date: Tue, 21 May 2024 17:50:06 +0300 Subject: [PATCH] [FunC] Produce an error on get methods hash (method_id) collision --- .../func/auto-tests/tests/invalid-get-method-2.fc | 15 +++++++++++++++ crypto/func/builtins.cpp | 2 +- crypto/func/func.h | 2 +- crypto/func/parse-func.cpp | 6 ++++++ 4 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 crypto/func/auto-tests/tests/invalid-get-method-2.fc diff --git a/crypto/func/auto-tests/tests/invalid-get-method-2.fc b/crypto/func/auto-tests/tests/invalid-get-method-2.fc new file mode 100644 index 00000000..e2a8556b --- /dev/null +++ b/crypto/func/auto-tests/tests/invalid-get-method-2.fc @@ -0,0 +1,15 @@ +get int secret() pure { + return 0; +} +get int balanced() pure { + return 1; +} + +int main() { + return secret() + balanced(); +} + +{- +@compilation_should_fail +@stderr GET methods hash collision: `secret` and `balanced` produce the same hash +-} diff --git a/crypto/func/builtins.cpp b/crypto/func/builtins.cpp index aafa9bef..218e173d 100644 --- a/crypto/func/builtins.cpp +++ b/crypto/func/builtins.cpp @@ -28,7 +28,7 @@ using namespace std::literals::string_literals; */ int glob_func_cnt, undef_func_cnt, glob_var_cnt, const_cnt; -std::vector glob_func, glob_vars; +std::vector glob_func, glob_vars, glob_get_methods; std::set prohibited_var_names; SymDef* define_builtin_func_impl(const std::string& name, SymValAsmFunc* func_val) { diff --git a/crypto/func/func.h b/crypto/func/func.h index 0a79c712..faf71f5d 100644 --- a/crypto/func/func.h +++ b/crypto/func/func.h @@ -874,7 +874,7 @@ struct SymValConst : sym::SymValBase { }; extern int glob_func_cnt, undef_func_cnt, glob_var_cnt; -extern std::vector glob_func, glob_vars; +extern std::vector glob_func, glob_vars, glob_get_methods; extern std::set prohibited_var_names; /* diff --git a/crypto/func/parse-func.cpp b/crypto/func/parse-func.cpp index 4e73247c..f2e48f33 100644 --- a/crypto/func/parse-func.cpp +++ b/crypto/func/parse-func.cpp @@ -1579,6 +1579,11 @@ void parse_func_def(Lexer& lex) { if (is_get_method) { func_assert(method_id.is_null()); method_id = calculate_method_id_by_func_name(func_name.str); + for (const SymDef* other : glob_get_methods) { + if (!td::cmp(dynamic_cast(other->value)->method_id, method_id)) { + lex.cur().error(PSTRING() << "GET methods hash collision: `" << other->name() << "` and `" + func_name.str + "` produce the same hash. Consider renaming one of these functions."); + } + } } TypeExpr* func_type = TypeExpr::new_map(extract_total_arg_type(arg_list), ret_type); func_type = compute_type_closure(func_type, type_vars); @@ -1698,6 +1703,7 @@ void parse_func_def(Lexer& lex) { lex.cur().error("cannot set unknown function `"s + func_name.str + "` as a get method"); } val->flags |= SymValFunc::flagGetMethod; + glob_get_methods.push_back(func_sym); } if (verbosity >= 1) { std::cerr << "new type of function " << func_name.str << " : " << func_type << std::endl;