diff --git a/src/Expr.cc b/src/Expr.cc index dd514df74b..04bee8aba7 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -4026,7 +4026,26 @@ Val* RecordCoerceExpr::Fold(Val* v) const Type()->AsRecordType()->FieldDecl(i)->FindAttr(ATTR_DEFAULT); if ( def ) - val->Assign(i, def->AttrExpr()->Eval(0)); + { + Val* def_val = def->AttrExpr()->Eval(0); + BroType* def_type = def_val->Type(); + BroType* field_type = Type()->AsRecordType()->FieldType(i); + + if ( def_type->Tag() == TYPE_RECORD && + field_type->Tag() == TYPE_RECORD && + ! same_type(def_type, field_type) ) + { + Val* tmp = def_val->AsRecordVal()->CoerceTo( + field_type->AsRecordType()); + if ( tmp ) + { + Unref(def_val); + def_val = tmp; + } + } + + val->Assign(i, def_val); + } else val->Assign(i, 0); } diff --git a/src/Val.cc b/src/Val.cc index 5133550236..dd86e71a9e 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -2560,10 +2560,22 @@ RecordVal::RecordVal(RecordType* t) : MutableVal(t) Attributes* a = record_type->FieldDecl(i)->attrs; Attr* def_attr = a ? a->FindAttr(ATTR_DEFAULT) : 0; Val* def = def_attr ? def_attr->AttrExpr()->Eval(0) : 0; + BroType* type = record_type->FieldDecl(i)->type; + + if ( def && type->Tag() == TYPE_RECORD && + def->Type()->Tag() == TYPE_RECORD && + ! same_type(def->Type(), type) ) + { + Val* tmp = def->AsRecordVal()->CoerceTo(type->AsRecordType()); + if ( tmp ) + { + Unref(def); + def = tmp; + } + } if ( ! def && ! (a && a->FindAttr(ATTR_OPTIONAL)) ) { - BroType* type = record_type->FieldDecl(i)->type; TypeTag tag = type->Tag(); if ( tag == TYPE_RECORD ) diff --git a/testing/btest/Baseline/language.record-default-coercion/out b/testing/btest/Baseline/language.record-default-coercion/out index 2f0e6cd17d..bf76ba5033 100644 --- a/testing/btest/Baseline/language.record-default-coercion/out +++ b/testing/btest/Baseline/language.record-default-coercion/out @@ -1,3 +1,21 @@ +[bar=4321, foo=[foo=1234, quux=9876]] +[foo=1234, quux=9876] +9876 +[bar=4231, foo=[foo=1000, quux=9876]] +[foo=1000, quux=9876] +9876 +[bar=4321, foo=[foo=10, quux=42]] +[foo=10, quux=42] +42 +[bar=100, foo=[foo=1234, quux=9876]] +[foo=1234, quux=9876] +9876 +[bar=100, foo=[foo=1001, quux=9876]] +[foo=1001, quux=9876] +9876 +[bar=100, foo=[foo=11, quux=7]] +[foo=11, quux=7] +7 [a=13, c=13, v=[]] 0 [a=13, c=13, v=[test]] diff --git a/testing/btest/language/record-default-coercion.bro b/testing/btest/language/record-default-coercion.bro index 7e717c39e2..822b845f65 100644 --- a/testing/btest/language/record-default-coercion.bro +++ b/testing/btest/language/record-default-coercion.bro @@ -7,12 +7,42 @@ type MyRecord: record { v: vector of string &default=vector(); }; -event bro_init() +type Foo: record { + foo: count; + quux: count &default=9876; +}; + +type Bar: record { + bar: count; + foo: Foo &default=[$foo=1234]; +}; + +function print_bar(b: Bar) { - local r: MyRecord = [$c=13]; - print r; - print |r$v|; - r$v[|r$v|] = "test"; - print r; - print |r$v|; + print b; + print b$foo; + print b$foo$quux; } + +global bar: Bar = [$bar=4321]; +global bar2: Bar = [$bar=4231, $foo=[$foo=1000]]; +global bar3: Bar = [$bar=4321, $foo=[$foo=10, $quux=42]]; + +print_bar(bar); +print_bar(bar2); +print_bar(bar3); + +local bar4: Bar = [$bar=100]; +local bar5: Bar = [$bar=100, $foo=[$foo=1001]]; +local bar6: Bar = [$bar=100, $foo=[$foo=11, $quux=7]]; + +print_bar(bar4); +print_bar(bar5); +print_bar(bar6); + +local r: MyRecord = [$c=13]; +print r; +print |r$v|; +r$v[|r$v|] = "test"; +print r; +print |r$v|;