mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
Fix FunC UB (#656)
* Fix UB in func * Improve optimizing int consts and unused variables in FunC * Bump funC version to 0.4.3 * Fix analyzing repeat loop --------- Co-authored-by: SpyCheese <mikle98@yandex.ru>
This commit is contained in:
parent
f51eb2d747
commit
8eb167b76a
8 changed files with 31 additions and 8 deletions
|
@ -179,7 +179,7 @@ void VarDescr::set_const_nan() {
|
||||||
|
|
||||||
void VarDescr::operator|=(const VarDescr& y) {
|
void VarDescr::operator|=(const VarDescr& y) {
|
||||||
val &= y.val;
|
val &= y.val;
|
||||||
if (is_int_const() && cmp(int_const, y.int_const) != 0) {
|
if (is_int_const() && y.is_int_const() && cmp(int_const, y.int_const) != 0) {
|
||||||
val &= ~_Const;
|
val &= ~_Const;
|
||||||
}
|
}
|
||||||
if (!(val & _Const)) {
|
if (!(val & _Const)) {
|
||||||
|
|
|
@ -388,7 +388,7 @@ bool Op::compute_used_vars(const CodeBlob& code, bool edit) {
|
||||||
for (; l_it < left.cend(); ++l_it, ++r_it) {
|
for (; l_it < left.cend(); ++l_it, ++r_it) {
|
||||||
if (std::find(l_it + 1, left.cend(), *l_it) == left.cend()) {
|
if (std::find(l_it + 1, left.cend(), *l_it) == left.cend()) {
|
||||||
auto p = next_var_info[*l_it];
|
auto p = next_var_info[*l_it];
|
||||||
new_var_info.add_var(*r_it, !p || p->is_unused());
|
new_var_info.add_var(*r_it, edit && (!p || p->is_unused()));
|
||||||
new_left.push_back(*l_it);
|
new_left.push_back(*l_it);
|
||||||
new_right.push_back(*r_it);
|
new_right.push_back(*r_it);
|
||||||
}
|
}
|
||||||
|
@ -500,7 +500,12 @@ bool Op::compute_used_vars(const CodeBlob& code, bool edit) {
|
||||||
}
|
}
|
||||||
changes = (new_var_info.size() == n);
|
changes = (new_var_info.size() == n);
|
||||||
} while (changes <= edit);
|
} while (changes <= edit);
|
||||||
|
assert(left.size() == 1);
|
||||||
|
bool last = new_var_info.count_used(left) == 0;
|
||||||
new_var_info += left;
|
new_var_info += left;
|
||||||
|
if (last) {
|
||||||
|
new_var_info[left[0]]->flags |= VarDescr::_Last;
|
||||||
|
}
|
||||||
return set_var_info(std::move(new_var_info));
|
return set_var_info(std::move(new_var_info));
|
||||||
}
|
}
|
||||||
case _Again: {
|
case _Again: {
|
||||||
|
|
|
@ -29,8 +29,12 @@ using namespace std::literals::string_literals;
|
||||||
|
|
||||||
int glob_func_cnt, undef_func_cnt, glob_var_cnt, const_cnt;
|
int glob_func_cnt, undef_func_cnt, glob_var_cnt, const_cnt;
|
||||||
std::vector<SymDef*> glob_func, glob_vars;
|
std::vector<SymDef*> glob_func, glob_vars;
|
||||||
|
std::set<std::string> prohibited_var_names;
|
||||||
|
|
||||||
SymDef* predefine_builtin_func(std::string name, TypeExpr* func_type) {
|
SymDef* predefine_builtin_func(std::string name, TypeExpr* func_type) {
|
||||||
|
if (name.back() == '_') {
|
||||||
|
prohibited_var_names.insert(name);
|
||||||
|
}
|
||||||
sym_idx_t name_idx = sym::symbols.lookup(name, 1);
|
sym_idx_t name_idx = sym::symbols.lookup(name, 1);
|
||||||
if (sym::symbols.is_keyword(name_idx)) {
|
if (sym::symbols.is_keyword(name_idx)) {
|
||||||
std::cerr << "fatal: global function `" << name << "` already defined as a keyword" << std::endl;
|
std::cerr << "fatal: global function `" << name << "` already defined as a keyword" << std::endl;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <set>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
@ -40,7 +41,7 @@ extern std::string generated_from;
|
||||||
|
|
||||||
constexpr int optimize_depth = 20;
|
constexpr int optimize_depth = 20;
|
||||||
|
|
||||||
const std::string func_version{"0.4.2"};
|
const std::string func_version{"0.4.3"};
|
||||||
|
|
||||||
enum Keyword {
|
enum Keyword {
|
||||||
_Eof = -1,
|
_Eof = -1,
|
||||||
|
@ -839,6 +840,7 @@ struct SymValConst : sym::SymValBase {
|
||||||
|
|
||||||
extern int glob_func_cnt, undef_func_cnt, glob_var_cnt;
|
extern int glob_func_cnt, undef_func_cnt, glob_var_cnt;
|
||||||
extern std::vector<SymDef*> glob_func, glob_vars;
|
extern std::vector<SymDef*> glob_func, glob_vars;
|
||||||
|
extern std::set<std::string> prohibited_var_names;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
|
|
|
@ -205,6 +205,10 @@ int Expr::predefine_vars() {
|
||||||
case _Var:
|
case _Var:
|
||||||
if (!sym) {
|
if (!sym) {
|
||||||
assert(val < 0 && here.defined());
|
assert(val < 0 && here.defined());
|
||||||
|
if (prohibited_var_names.count(sym::symbols.get_name(~val))) {
|
||||||
|
throw src::ParseError{
|
||||||
|
here, PSTRING() << "symbol `" << sym::symbols.get_name(~val) << "` cannot be redefined as a variable"};
|
||||||
|
}
|
||||||
sym = sym::define_symbol(~val, false, here);
|
sym = sym::define_symbol(~val, false, here);
|
||||||
// std::cerr << "predefining variable " << sym::symbols.get_name(~val) << std::endl;
|
// std::cerr << "predefining variable " << sym::symbols.get_name(~val) << std::endl;
|
||||||
if (!sym) {
|
if (!sym) {
|
||||||
|
|
|
@ -172,6 +172,10 @@ FormalArg parse_formal_arg(Lexer& lex, int fa_idx) {
|
||||||
lex.expect(_Ident, "formal parameter name");
|
lex.expect(_Ident, "formal parameter name");
|
||||||
}
|
}
|
||||||
loc = lex.cur().loc;
|
loc = lex.cur().loc;
|
||||||
|
if (prohibited_var_names.count(sym::symbols.get_name(lex.cur().val))) {
|
||||||
|
throw src::ParseError{
|
||||||
|
loc, PSTRING() << "symbol `" << sym::symbols.get_name(lex.cur().val) << "` cannot be redefined as a variable"};
|
||||||
|
}
|
||||||
SymDef* new_sym_def = sym::define_symbol(lex.cur().val, true, loc);
|
SymDef* new_sym_def = sym::define_symbol(lex.cur().val, true, loc);
|
||||||
if (!new_sym_def) {
|
if (!new_sym_def) {
|
||||||
lex.cur().error_at("cannot define symbol `", "`");
|
lex.cur().error_at("cannot define symbol `", "`");
|
||||||
|
@ -397,7 +401,7 @@ bool check_global_func(const Lexem& cur, sym_idx_t func_name = 0) {
|
||||||
def = sym::define_global_symbol(func_name, 0, cur.loc);
|
def = sym::define_global_symbol(func_name, 0, cur.loc);
|
||||||
assert(def && "cannot define global function");
|
assert(def && "cannot define global function");
|
||||||
++undef_func_cnt;
|
++undef_func_cnt;
|
||||||
make_new_glob_func(def, TypeExpr::new_hole()); // was: ... ::new_func()
|
make_new_glob_func(def, TypeExpr::new_func()); // was: ... ::new_func()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
SymVal* val = dynamic_cast<SymVal*>(def->value);
|
SymVal* val = dynamic_cast<SymVal*>(def->value);
|
||||||
|
@ -1369,6 +1373,10 @@ std::vector<TypeExpr*> parse_type_var_list(Lexer& lex) {
|
||||||
throw src::ParseError{lex.cur().loc, "free type identifier expected"};
|
throw src::ParseError{lex.cur().loc, "free type identifier expected"};
|
||||||
}
|
}
|
||||||
auto loc = lex.cur().loc;
|
auto loc = lex.cur().loc;
|
||||||
|
if (prohibited_var_names.count(sym::symbols.get_name(lex.cur().val))) {
|
||||||
|
throw src::ParseError{loc, PSTRING() << "symbol `" << sym::symbols.get_name(lex.cur().val)
|
||||||
|
<< "` cannot be redefined as a variable"};
|
||||||
|
}
|
||||||
SymDef* new_sym_def = sym::define_symbol(lex.cur().val, true, loc);
|
SymDef* new_sym_def = sym::define_symbol(lex.cur().val, true, loc);
|
||||||
if (!new_sym_def || new_sym_def->value) {
|
if (!new_sym_def || new_sym_def->value) {
|
||||||
lex.cur().error_at("redefined type variable `", "`");
|
lex.cur().error_at("redefined type variable `", "`");
|
||||||
|
|
|
@ -32,8 +32,8 @@ int scope_level;
|
||||||
|
|
||||||
SymTable<100003> symbols;
|
SymTable<100003> symbols;
|
||||||
|
|
||||||
SymDef* sym_def[symbols.hprime];
|
SymDef* sym_def[symbols.hprime + 1];
|
||||||
SymDef* global_sym_def[symbols.hprime];
|
SymDef* global_sym_def[symbols.hprime + 1];
|
||||||
std::vector<std::pair<int, SymDef>> symbol_stack;
|
std::vector<std::pair<int, SymDef>> symbol_stack;
|
||||||
std::vector<src::SrcLocation> scope_opened_at;
|
std::vector<src::SrcLocation> scope_opened_at;
|
||||||
|
|
||||||
|
|
|
@ -161,8 +161,8 @@ struct SymDef {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
extern SymDef* sym_def[symbols.hprime];
|
extern SymDef* sym_def[symbols.hprime + 1];
|
||||||
extern SymDef* global_sym_def[symbols.hprime];
|
extern SymDef* global_sym_def[symbols.hprime + 1];
|
||||||
extern std::vector<std::pair<int, SymDef>> symbol_stack;
|
extern std::vector<std::pair<int, SymDef>> symbol_stack;
|
||||||
extern std::vector<src::SrcLocation> scope_opened_at;
|
extern std::vector<src::SrcLocation> scope_opened_at;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue