diff --git a/CHANGES b/CHANGES index 1ddefe2b24..b32e7c023c 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,13 @@ + +4.1.0-dev.545 | 2021-04-26 11:14:49 -0700 + + * GH-1483: Improve error for mismatched container initialization types (Jon Siwek, Corelight) + + For example, trying to assign a vector, table, set, or record + constructor expression to a global variable of a different type now + provides a more explanatory error message than the previous + "Val::CONVERTER" fatal-error and coredump. + 4.1.0-dev.543 | 2021-04-26 09:53:53 -0700 * Update btest baselines for --enable-mobile-ipv6 builds (Tim Wojtulewicz, Corelight) diff --git a/VERSION b/VERSION index d5dd78a142..226661d28d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.1.0-dev.543 +4.1.0-dev.545 diff --git a/src/Expr.cc b/src/Expr.cc index 56f0420b05..0550720ec0 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -24,6 +24,18 @@ namespace zeek::detail { +static bool init_tag_check(const Expr* expr, const char* name, + TypeTag expect_tag, TypeTag init_tag) + { + if ( expect_tag == init_tag ) + return true; + + auto msg = util::fmt("unexpected use of %s in '%s' initialization", + name, type_name(init_tag)); + expr->Error(msg); + return false; + } + const char* expr_name(BroExprTag t) { static const char* expr_names[int(NUM_EXPRS)] = { @@ -3215,6 +3227,15 @@ RecordConstructorExpr::~RecordConstructorExpr() ValPtr RecordConstructorExpr::InitVal(const zeek::Type* t, ValPtr aggr) const { + if ( IsError() ) + { + Error("bad record initializer"); + return nullptr; + } + + if ( ! init_tag_check(this, "record constructor", TYPE_RECORD, t->Tag()) ) + return nullptr; + auto v = Eval(nullptr); if ( v ) @@ -3394,6 +3415,9 @@ ValPtr TableConstructorExpr::InitVal(const zeek::Type* t, ValPtr aggr) const if ( IsError() ) return nullptr; + if ( ! init_tag_check(this, "table constructor", TYPE_TABLE, t->Tag()) ) + return nullptr; + auto tt = GetType(); auto tval = aggr ? @@ -3508,6 +3532,9 @@ ValPtr SetConstructorExpr::InitVal(const zeek::Type* t, ValPtr aggr) const if ( IsError() ) return nullptr; + if ( ! init_tag_check(this, "set constructor", TYPE_TABLE, t->Tag()) ) + return nullptr; + const auto& index_type = t->AsTableType()->GetIndices(); auto tt = GetType(); auto tval = aggr ? @@ -3606,6 +3633,9 @@ ValPtr VectorConstructorExpr::InitVal(const zeek::Type* t, ValPtr aggr) const if ( IsError() ) return nullptr; + if ( ! init_tag_check(this, "vector constructor", TYPE_VECTOR, t->Tag()) ) + return nullptr; + auto vt = GetType(); auto vec = aggr ? VectorValPtr{AdoptRef{}, aggr.release()->AsVectorVal()} : @@ -3864,6 +3894,15 @@ RecordCoerceExpr::RecordCoerceExpr(ExprPtr arg_op, RecordTypePtr r) ValPtr RecordCoerceExpr::InitVal(const zeek::Type* t, ValPtr aggr) const { + if ( IsError() ) + { + Error("bad record initializer"); + return nullptr; + } + + if ( ! init_tag_check(this, "record", TYPE_RECORD, t->Tag()) ) + return nullptr; + if ( auto v = Eval(nullptr) ) { RecordVal* rv = v->AsRecordVal(); diff --git a/testing/btest/Baseline/language.mismatched-container-ctor-types/.stderr b/testing/btest/Baseline/language.mismatched-container-ctor-types/.stderr new file mode 100644 index 0000000000..a1932da4a1 --- /dev/null +++ b/testing/btest/Baseline/language.mismatched-container-ctor-types/.stderr @@ -0,0 +1,11 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +error in <...>/mismatched-container-ctor-types.zeek, line 6: unexpected use of vector constructor in 'table' initialization (vector()) +error in <...>/mismatched-container-ctor-types.zeek, line 7: unexpected use of table constructor in 'vector' initialization (table()) +error in <...>/mismatched-container-ctor-types.zeek, line 8: unexpected use of set constructor in 'vector' initialization (set()) +error in <...>/mismatched-container-ctor-types.zeek, line 9: unexpected use of record constructor in 'vector' initialization ([]) +error in <...>/mismatched-container-ctor-types.zeek, line 10: unexpected use of record in 'vector' initialization ((coerce [] to R)) +error in <...>/mismatched-container-ctor-types.zeek, line 12: type clash in assignment (lt = vector()) +error in <...>/mismatched-container-ctor-types.zeek, line 13: type clash in assignment (lv0 = table()) +error in <...>/mismatched-container-ctor-types.zeek, line 14: type clash in assignment (lv1 = set()) +error in <...>/mismatched-container-ctor-types.zeek, line 15: type clash in assignment (lv2 = []) +error in <...>/mismatched-container-ctor-types.zeek, line 16: type clash in assignment (lv3 = (coerce [] to R)) diff --git a/testing/btest/language/mismatched-container-ctor-types.zeek b/testing/btest/language/mismatched-container-ctor-types.zeek new file mode 100644 index 0000000000..8937ccfdb3 --- /dev/null +++ b/testing/btest/language/mismatched-container-ctor-types.zeek @@ -0,0 +1,16 @@ +# @TEST-EXEC-FAIL: zeek -b %INPUT +# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff .stderr +# @TEST-DOC: Mismatched type-constructor initializations fail with reasonable error message + +type R: record { a: bool &default=T; }; +global t: table[string] of vector of string = vector(); +global v0: vector of string = table(); +global v1: vector of string = set(); +global v2: vector of string = []; +global v3: vector of string = R(); + +local lt: table[string] of vector of string = vector(); +local lv0: vector of string = table(); +local lv1: vector of string = set(); +local lv2: vector of string = []; +local lv3: vector of string = R();