diff --git a/CHANGES b/CHANGES index 6de6c2c408..f02a65a49c 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,11 @@ +8.0.0-dev.703 | 2025-07-23 13:37:56 +0200 + + * Type/RecordType: Make table returned by GetRecordFieldsVal() ordered (Arne Welzel, Corelight) + + Seems only reasonable to provide that guarantee as pointed out in #4674. + + * Update doc submodule [nomail] [skip ci] (zeek-bot) + 8.0.0-dev.700 | 2025-07-22 11:40:19 -0700 * Update zeek-af_packet-plugin submodule to fix initialization [nomail] (Tim Wojtulewicz, Corelight) diff --git a/VERSION b/VERSION index 1ae0b95185..a5dd37fdf1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.0.0-dev.700 +8.0.0-dev.703 diff --git a/src/Type.cc b/src/Type.cc index f7fc1d6b9e..5628470e74 100644 --- a/src/Type.cc +++ b/src/Type.cc @@ -1213,7 +1213,12 @@ static string container_type_name(const Type* ft) { TableValPtr RecordType::GetRecordFieldsVal(const RecordVal* rv) const { static auto record_field = id::find_type("record_field"); static auto record_field_table = id::find_type("record_field_table"); - auto rval = make_intrusive(record_field_table); + + auto attrs = zeek::make_intrusive(record_field_table, + /*in_record=*/false, + /*is_global=*/false); + attrs->AddAttr(make_intrusive(detail::ATTR_ORDERED)); + auto rval = make_intrusive(record_field_table, std::move(attrs)); for ( int i = 0; i < NumFields(); ++i ) { const auto& ft = GetFieldType(i); diff --git a/src/Type.h b/src/Type.h index e17de61cc2..64b5ea7fef 100644 --- a/src/Type.h +++ b/src/Type.h @@ -697,7 +697,10 @@ public: /** * Returns a "record_field_table" value for introspection purposes. * @param rv an optional record value, if given the values of - * all fields will be provided in the returned table. + * all fields will be provided in the returned table. The table + * is initialized with the &ordered attribute such that iterating over + * the table will yield entries for fields in the same order as they + * are kept in the record type types list. */ TableValPtr GetRecordFieldsVal(const RecordVal* rv = nullptr) const; diff --git a/src/zeek.bif b/src/zeek.bif index 6e60ed9904..d4df84d0e1 100644 --- a/src/zeek.bif +++ b/src/zeek.bif @@ -2403,7 +2403,10 @@ function lookup_ID%(id: string%) : any ## ## rec: The record value or type to inspect. ## -## Returns: A table that describes the fields of a record. +## Returns: A table that describes the fields of a record. The returned table has +## the :zeek:attr:`&ordered` attribute set. Iterating over the table will +## yield entries for the fields in the same order as the fields were +## declared. function record_fields%(rec: any%): record_field_table %{ static auto record_field_table = zeek::id::find_type("record_field_table"); diff --git a/testing/btest/Baseline/bifs.records_fields/out b/testing/btest/Baseline/bifs.records_fields/out index 6a6921fc6a..0898f3f807 100644 --- a/testing/btest/Baseline/bifs.records_fields/out +++ b/testing/btest/Baseline/bifs.records_fields/out @@ -2,9 +2,9 @@ [a=42, b=Foo, c=, d=Bar, e=tt] { [a] = [type_name=count, log=F, value=42, default_val=, optional=F], -[d] = [type_name=string, log=T, value=Bar, default_val=, optional=F], [b] = [type_name=string, log=F, value=Foo, default_val=Foo, optional=T], [c] = [type_name=double, log=F, value=, default_val=, optional=T], +[d] = [type_name=string, log=T, value=Bar, default_val=, optional=F], [e] = [type_name=any, log=F, value=tt, default_val=, optional=F] } c value, F @@ -12,27 +12,27 @@ c default , F c optional, T { [a] = [type_name=bool, log=F, value=, default_val=, optional=F], -[d] = [type_name=string, log=T, value=, default_val=, optional=F], -[f] = [type_name=enum Monochrome::color, log=T, value=, default_val=, optional=F], [b] = [type_name=string, log=F, value=, default_val=Bar, optional=T], [c] = [type_name=double, log=F, value=, default_val=, optional=T], -[m] = [type_name=record myrec, log=F, value=, default_val=, optional=F], -[e] = [type_name=enum color, log=F, value=, default_val=BLUE, optional=T] +[d] = [type_name=string, log=T, value=, default_val=, optional=F], +[e] = [type_name=enum color, log=F, value=, default_val=BLUE, optional=T], +[f] = [type_name=enum Monochrome::color, log=T, value=, default_val=, optional=F], +[m] = [type_name=record myrec, log=F, value=, default_val=, optional=F] } { [a] = [type_name=bool, log=F, value=, default_val=, optional=F], -[d] = [type_name=string, log=T, value=, default_val=, optional=F], -[f] = [type_name=enum Monochrome::color, log=T, value=, default_val=, optional=F], [b] = [type_name=string, log=F, value=, default_val=Bar, optional=T], [c] = [type_name=double, log=F, value=, default_val=, optional=T], -[m] = [type_name=record myrec, log=F, value=, default_val=, optional=F], -[e] = [type_name=enum color, log=F, value=, default_val=BLUE, optional=T] +[d] = [type_name=string, log=T, value=, default_val=, optional=F], +[e] = [type_name=enum color, log=F, value=, default_val=BLUE, optional=T], +[f] = [type_name=enum Monochrome::color, log=T, value=, default_val=, optional=F], +[m] = [type_name=record myrec, log=F, value=, default_val=, optional=F] } { [a] = [type_name=count, log=F, value=42, default_val=, optional=F], -[d] = [type_name=string, log=T, value=Bar, default_val=, optional=F], [b] = [type_name=string, log=F, value=Foo, default_val=Foo, optional=T], [c] = [type_name=double, log=F, value=, default_val=, optional=T], +[d] = [type_name=string, log=T, value=Bar, default_val=, optional=F], [e] = [type_name=any, log=F, value=mystring, default_val=, optional=F] } { @@ -43,26 +43,26 @@ c optional, T } { [a] = [type_name=bool, log=F, value=, default_val=, optional=F], -[d] = [type_name=string, log=T, value=, default_val=, optional=F], -[f] = [type_name=enum Monochrome::color, log=T, value=, default_val=, optional=F], [b] = [type_name=string, log=F, value=, default_val=Bar, optional=T], [c] = [type_name=double, log=F, value=, default_val=, optional=T], -[m] = [type_name=record myrec, log=F, value=, default_val=, optional=F], -[e] = [type_name=enum color, log=F, value=, default_val=BLUE, optional=T] +[d] = [type_name=string, log=T, value=, default_val=, optional=F], +[e] = [type_name=enum color, log=F, value=, default_val=BLUE, optional=T], +[f] = [type_name=enum Monochrome::color, log=T, value=, default_val=, optional=F], +[m] = [type_name=record myrec, log=F, value=, default_val=, optional=F] } { [a] = [type_name=count, log=F, value=, default_val=, optional=F], -[d] = [type_name=string, log=T, value=, default_val=, optional=F], [b] = [type_name=string, log=F, value=, default_val=Foo, optional=T], [c] = [type_name=double, log=F, value=, default_val=, optional=T], +[d] = [type_name=string, log=T, value=, default_val=, optional=F], [e] = [type_name=any, log=F, value=, default_val=, optional=F] } { [a] = [type_name=set[double], log=F, value=, default_val=, optional=F], -[d] = [type_name=table[double,string] of table[string] of vector of string, log=F, value=, default_val=, optional=F], -[f] = [type_name=vector of enum color, log=F, value=, default_val=, optional=F], [b] = [type_name=set[double,string], log=F, value=, default_val=, optional=F], [c] = [type_name=set[double,record tt], log=F, value=, default_val=, optional=F], -[g] = [type_name=table[string] of enum color, log=F, value=, default_val=, optional=F], -[e] = [type_name=vector of vector of string, log=F, value=, default_val=, optional=F] +[d] = [type_name=table[double,string] of table[string] of vector of string, log=F, value=, default_val=, optional=F], +[e] = [type_name=vector of vector of string, log=F, value=, default_val=, optional=F], +[f] = [type_name=vector of enum color, log=F, value=, default_val=, optional=F], +[g] = [type_name=table[string] of enum color, log=F, value=, default_val=, optional=F] } diff --git a/testing/btest/Baseline/core.record-field-redef/output b/testing/btest/Baseline/core.record-field-redef/output index f35518cafa..98396cb099 100644 --- a/testing/btest/Baseline/core.record-field-redef/output +++ b/testing/btest/Baseline/core.record-field-redef/output @@ -1,10 +1,10 @@ ### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. Info record_fields\x0a, { +[ts] = [type_name=time, log=T, value=, default_val=, optional=F], +[msg] = [type_name=string, log=T, value=, default_val=, optional=F], [extra1] = [type_name=string, log=F, value=, default_val=, optional=T], [extra2] = [type_name=string, log=F, value=, default_val=, optional=T], -[ts] = [type_name=time, log=T, value=, default_val=, optional=F], [extra3] = [type_name=string, log=T, value=, default_val=, optional=T], -[msg] = [type_name=string, log=T, value=, default_val=, optional=F], [extra4] = [type_name=string, log=T, value=, default_val=, optional=T] } Info record, [ts=XXXXXXXXXX.XXXXXX, msg=msg, extra1=extra1 value, extra2=extra2 value, extra3=extra3 value, extra4=extra4 value] diff --git a/testing/btest/Baseline/doc.zeekygen.declaring_script/out b/testing/btest/Baseline/doc.zeekygen.declaring_script/out index 81b9f6a93d..f89f511294 100644 --- a/testing/btest/Baseline/doc.zeekygen.declaring_script/out +++ b/testing/btest/Baseline/doc.zeekygen.declaring_script/out @@ -5,6 +5,6 @@ Conn::Info$speculative_service, policy/protocols/conn/speculative-service.zeek Conn::Info$orig_l2_addr, policy/protocols/conn/mac-logging.zeek MyModule::Info, my-module.zeek MyModule::Info$ts, original, my-module.zeek +MyModule::Info$prefix, original, my-module.zeek MyModule::Info$addl, redef, redef-it.zeek MyModule::Info$more, redef, pkg1/redef-more.zeek -MyModule::Info$prefix, original, my-module.zeek diff --git a/testing/btest/Baseline/spicy.export-bitfield/output b/testing/btest/Baseline/spicy.export-bitfield/output index 2b6d89a367..d5c860ab82 100644 --- a/testing/btest/Baseline/spicy.export-bitfield/output +++ b/testing/btest/Baseline/spicy.export-bitfield/output @@ -2,14 +2,14 @@ { [a] = [type_name=count, log=F, value=80, default_val=, optional=T], [bf] = [type_name=record , log=F, value=[x1=79, y1=15, z1=4], default_val=, optional=T], +[x2] = [type_name=count, log=F, value=83, default_val=, optional=T], [y2] = [type_name=count, log=F, value=3, default_val=, optional=T], [z2] = [type_name=count, log=F, value=5, default_val=, optional=T], -[x2] = [type_name=count, log=F, value=83, default_val=, optional=T], [b] = [type_name=count, log=F, value=84, default_val=, optional=T] } { -[z1] = [type_name=count, log=F, value=4, default_val=, optional=F], +[x1] = [type_name=count, log=F, value=79, default_val=, optional=F], [y1] = [type_name=count, log=F, value=15, default_val=, optional=F], -[x1] = [type_name=count, log=F, value=79, default_val=, optional=F] +[z1] = [type_name=count, log=F, value=4, default_val=, optional=F] } [a=80, bf=[x1=79, y1=15, z1=4], x2=83, y2=3, z2=5, b=84] diff --git a/testing/btest/Baseline/spicy.export-type-with-fields/output b/testing/btest/Baseline/spicy.export-type-with-fields/output index 40382d9da7..520d12ae9b 100644 --- a/testing/btest/Baseline/spicy.export-type-with-fields/output +++ b/testing/btest/Baseline/spicy.export-type-with-fields/output @@ -3,12 +3,12 @@ name=x log=F === X1 name=x log=F -name=z log=F name=y log=F +name=z log=F === X2 name=x log=T -name=z log=T name=y log=T +name=z log=T === X3 name=x log=F name=z log=T diff --git a/testing/btest/Baseline/spicy.export-types/output b/testing/btest/Baseline/spicy.export-types/output index bf6b8458ae..ed1f788786 100644 --- a/testing/btest/Baseline/spicy.export-types/output +++ b/testing/btest/Baseline/spicy.export-types/output @@ -8,26 +8,26 @@ Test::type_enum_C Test::type_enum_Undef Test::type_record_u, { [s] = [type_name=string, log=F, value=, default_val=], -[u2] = [type_name=record , log=F, value=, default_val=], -[b] = [type_name=bool, log=F, value=, default_val=] +[b] = [type_name=bool, log=F, value=, default_val=], +[u2] = [type_name=record , log=F, value=, default_val=] } Test::u Test::u2 XYZ::type_record_sss, { [a] = [type_name=addr, log=F, value=, default_val=], -[v] = [type_name=vector of string, log=F, value=, default_val=], -[iv] = [type_name=interval, log=F, value=, default_val=], -[t] = [type_name=time, log=F, value=, default_val=], -[s] = [type_name=set[enum], log=F, value=, default_val=], -[p] = [type_name=port, log=F, value=, default_val=], [b] = [type_name=string, log=F, value=, default_val=], -[i] = [type_name=int, log=F, value=, default_val=], -[o] = [type_name=string, log=F, value=, default_val=], -[m] = [type_name=table[addr] of string, log=F, value=, default_val=], -[u] = [type_name=record , log=F, value=, default_val=], -[j] = [type_name=count, log=F, value=, default_val=], [e] = [type_name=enum, log=F, value=, default_val=], -[r] = [type_name=double, log=F, value=, default_val=] +[i] = [type_name=int, log=F, value=, default_val=], +[iv] = [type_name=interval, log=F, value=, default_val=], +[j] = [type_name=count, log=F, value=, default_val=], +[m] = [type_name=table[addr] of string, log=F, value=, default_val=], +[o] = [type_name=string, log=F, value=, default_val=], +[p] = [type_name=port, log=F, value=, default_val=], +[r] = [type_name=double, log=F, value=, default_val=], +[s] = [type_name=set[enum], log=F, value=, default_val=], +[t] = [type_name=time, log=F, value=, default_val=], +[u] = [type_name=record , log=F, value=, default_val=], +[v] = [type_name=vector of string, log=F, value=, default_val=] } type_record_u2, { [t] = [type_name=record , log=F, value=, default_val=]