From c6143715cc29ae23dad202b2580083099d8f61d2 Mon Sep 17 00:00:00 2001 From: SpyCheese Date: Mon, 23 Jan 2023 10:01:40 +0000 Subject: [PATCH] Fix some error handling in FunC (#599) --- crypto/func/builtins.cpp | 2 +- crypto/func/codegen.cpp | 20 ++++++++++++++------ crypto/func/func.h | 2 +- crypto/func/gen-abscode.cpp | 3 +++ crypto/func/parse-func.cpp | 21 ++++++++++++++------- 5 files changed, 33 insertions(+), 15 deletions(-) diff --git a/crypto/func/builtins.cpp b/crypto/func/builtins.cpp index 2c103d46..36f240d7 100644 --- a/crypto/func/builtins.cpp +++ b/crypto/func/builtins.cpp @@ -266,7 +266,7 @@ int emulate_div(int a, int b) { if ((b & (VarDescr::_NonZero | VarDescr::_Bit)) == (VarDescr::_NonZero | VarDescr::_Bit)) { return a; } else if ((b & (VarDescr::_NonZero | VarDescr::_Bool)) == (VarDescr::_NonZero | VarDescr::_Bool)) { - return emulate_negate(b); + return emulate_negate(a); } if (b & VarDescr::_Zero) { return VarDescr::_Int | VarDescr::_Nan; diff --git a/crypto/func/codegen.cpp b/crypto/func/codegen.cpp index 13b808ea..ac43d12a 100644 --- a/crypto/func/codegen.cpp +++ b/crypto/func/codegen.cpp @@ -663,12 +663,20 @@ bool Op::generate_code_step(Stack& stack) { stack.o << "REPEAT:<{"; stack.o.indent(); stack.forget_const(); - StackLayout layout1 = stack.vars(); - stack.mode &= ~Stack::_InlineFunc; - stack.mode |= Stack::_NeedRetAlt; - block0->generate_code_all(stack); - stack.enforce_state(std::move(layout1)); - stack.opt_show(); + if (block0->noreturn()) { + Stack stack_copy{stack}; + StackLayout layout1 = stack.vars(); + stack_copy.mode &= ~Stack::_InlineFunc; + stack_copy.mode |= Stack::_NeedRetAlt; + block0->generate_code_all(stack_copy); + } else { + StackLayout layout1 = stack.vars(); + stack.mode &= ~Stack::_InlineFunc; + stack.mode |= Stack::_NeedRetAlt; + block0->generate_code_all(stack); + stack.enforce_state(std::move(layout1)); + stack.opt_show(); + } stack.o.undent(); stack.o << "}>"; return true; diff --git a/crypto/func/func.h b/crypto/func/func.h index 0eeb9557..b979afb2 100644 --- a/crypto/func/func.h +++ b/crypto/func/func.h @@ -388,7 +388,7 @@ struct VarDescr { return val & _Const; } bool is_int_const() const { - return (val & (_Int | _Const)) == (_Int | _Const); + return (val & (_Int | _Const)) == (_Int | _Const) && int_const.not_null(); } bool always_nonpos() const { return val & _Neg; diff --git a/crypto/func/gen-abscode.cpp b/crypto/func/gen-abscode.cpp index cff40379..a2b98878 100644 --- a/crypto/func/gen-abscode.cpp +++ b/crypto/func/gen-abscode.cpp @@ -355,6 +355,9 @@ std::vector Expr::pre_compile(CodeBlob& code, std::vectorpre_compile(code, lval_globs); case _Var: case _Hole: + if (val < 0) { + throw src::ParseError{here, "unexpected variable definition"}; + } return {val}; case _VarApply: if (args[0]->cls == _Glob) { diff --git a/crypto/func/parse-func.cpp b/crypto/func/parse-func.cpp index 82462e79..011947d5 100644 --- a/crypto/func/parse-func.cpp +++ b/crypto/func/parse-func.cpp @@ -1372,7 +1372,7 @@ std::vector parse_type_var_list(Lexer& lex) { } auto loc = lex.cur().loc; SymDef* new_sym_def = sym::define_symbol(lex.cur().val, true, loc); - if (new_sym_def->value) { + if (!new_sym_def || new_sym_def->value) { lex.cur().error_at("redefined type variable `", "`"); } auto var = TypeExpr::new_var(idx); @@ -1582,8 +1582,15 @@ void parse_pragma(Lexer& lex) { char op = '='; bool eq = false; int sem_ver[3] = {0, 0, 0}; char segs = 1; + auto stoi = [&](const std::string& s) { + auto R = td::to_integer_safe(s); + if (R.is_error()) { + lex.cur().error("invalid semver format"); + } + return R.move_as_ok(); + }; if (lex.tp() == _Number) { - sem_ver[0] = std::stoi(lex.cur().str); + sem_ver[0] = stoi(lex.cur().str); } else if (lex.tp() == _Ident) { auto id1 = lex.cur().str; char ch1 = id1[0]; @@ -1600,9 +1607,9 @@ void parse_pragma(Lexer& lex) { if (id1.length() < 3) { lex.cur().error("expected number after comparator"); } - sem_ver[0] = std::stoi(id1.substr(2)); + sem_ver[0] = stoi(id1.substr(2)); } else { - sem_ver[0] = std::stoi(id1.substr(1)); + sem_ver[0] = stoi(id1.substr(1)); } } else { lex.cur().error("expected semver with optional comparator"); @@ -1612,7 +1619,7 @@ void parse_pragma(Lexer& lex) { if (lex.tp() != _Ident || lex.cur().str[0] != '.') { lex.cur().error("invalid semver format"); } - sem_ver[1] = std::stoi(lex.cur().str.substr(1)); + sem_ver[1] = stoi(lex.cur().str.substr(1)); segs = 2; lex.next(); } @@ -1620,7 +1627,7 @@ void parse_pragma(Lexer& lex) { if (lex.tp() != _Ident || lex.cur().str[0] != '.') { lex.cur().error("invalid semver format"); } - sem_ver[2] = std::stoi(lex.cur().str.substr(1)); + sem_ver[2] = stoi(lex.cur().str.substr(1)); segs = 3; lex.next(); } @@ -1630,7 +1637,7 @@ void parse_pragma(Lexer& lex) { std::string s; for (int idx = 0; idx < 3; idx++) { std::getline(iss, s, '.'); - func_ver[idx] = std::stoi(s); + func_ver[idx] = stoi(s); } // End parsing embedded semver std::string semver_expr;