From cf06ade325c8183e98b59ee75513445b28f64cb9 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 26 Aug 2020 14:24:36 -0700 Subject: [PATCH] GH-1122: Improve error for global record initialization exceptions --- src/Val.cc | 17 ++++++++++++++++- src/Var.cc | 10 +++++++++- .../language.record-global-init-exception/out | 2 ++ .../language/record-global-init-exception.zeek | 14 ++++++++++++++ 4 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 testing/btest/Baseline/language.record-global-init-exception/out create mode 100644 testing/btest/language/record-global-init-exception.zeek diff --git a/src/Val.cc b/src/Val.cc index 229bc37878..5f5276fb0d 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -2886,7 +2886,22 @@ RecordVal::RecordVal(RecordTypePtr t, bool init_fields) : Val(std::move(t)) { detail::Attributes* a = rt->FieldDecl(i)->attrs.get(); detail::Attr* def_attr = a ? a->Find(detail::ATTR_DEFAULT).get() : nullptr; - auto def = def_attr ? def_attr->GetExpr()->Eval(nullptr) : nullptr; + ValPtr def; + + if ( def_attr ) + try + { + def = def_attr->GetExpr()->Eval(nullptr); + } + catch ( InterpreterException& ) + { + if ( run_state::is_parsing ) + parse_time_records[rt].pop_back(); + + delete AsNonConstRecord(); + throw; + } + const auto& type = rt->FieldDecl(i)->type; if ( def && type->Tag() == TYPE_RECORD && diff --git a/src/Var.cc b/src/Var.cc index 448a8e049a..c849e5a39f 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -252,7 +252,15 @@ static void make_var(const IDPtr& id, TypePtr t, InitClass c, ExprPtr init, if ( t->Tag() == TYPE_RECORD ) { - aggr = make_intrusive(cast_intrusive(t)); + try + { + aggr = make_intrusive(cast_intrusive(t)); + } + catch ( InterpreterException& ) + { + id->Error("initialization failed"); + return; + } if ( init && t ) // Have an initialization and type is not deduced. diff --git a/testing/btest/Baseline/language.record-global-init-exception/out b/testing/btest/Baseline/language.record-global-init-exception/out new file mode 100644 index 0000000000..447f5f0b47 --- /dev/null +++ b/testing/btest/Baseline/language.record-global-init-exception/out @@ -0,0 +1,2 @@ +expression error in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.record-global-init-exception/record-global-init-exception.zeek, line 7: value used but not set (my_count) +error in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.record-global-init-exception/record-global-init-exception.zeek, line 14: initialization failed (my_record) diff --git a/testing/btest/language/record-global-init-exception.zeek b/testing/btest/language/record-global-init-exception.zeek new file mode 100644 index 0000000000..05debe0587 --- /dev/null +++ b/testing/btest/language/record-global-init-exception.zeek @@ -0,0 +1,14 @@ +# @TEST-EXEC-FAIL: zeek -b %INPUT >out 2>&1 +# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff out + +global my_count: count; + +type MyRecord: record { + f: count &default=my_count; +}; + +# This global initialization encounters the uninitialized 'my_count' when +# evaluating the &default expression. The test simply checking that the +# interpreter exception is caught and at least fails out with a nice error +# message instead of letting an uncaught exception cause termination. +global my_record = MyRecord();