diff --git a/src/spicy/spicyz/glue-compiler.cc b/src/spicy/spicyz/glue-compiler.cc index b4efc48dbf..375b45aea2 100644 --- a/src/spicy/spicyz/glue-compiler.cc +++ b/src/spicy/spicyz/glue-compiler.cc @@ -1173,7 +1173,7 @@ bool GlueCompiler::CreateSpicyHook(glue::Event* ev) { } namespace { -// Visitor creasting code to instantiate a Zeek type corresponding to a give +// Visitor creating code to instantiate a Zeek type corresponding to a give // HILTI type. // // Note: Any logic changes here must be reflected in the plugin driver's @@ -1194,6 +1194,30 @@ struct VisitorZeekType : hilti::visitor::PreOrdernamespace_() : hilti::ID(); } + result_t create_record_type(const hilti::ID& ns, const hilti::ID& local, + const std::vector& fields) { + if ( hilti::logger().isEnabled(ZeekPlugin) ) { + if ( ! fields.empty() ) { + SPICY_DEBUG(hilti::util::fmt("Creating Zeek record type %s::%s with fields:", ns, local)); + + for ( const auto& f : fields ) + SPICY_DEBUG(hilti::util::fmt(" %s", f.as() + .ctor() + .as() + .value()[0] + .as() + .ctor() + .as() + .value())); + } + else + SPICY_DEBUG(hilti::util::fmt("Creating (empty) Zeek record type %s::%s", ns, local)); + } + + return builder::call("zeek_rt::create_record_type", + {builder::string(ns), builder::string(local), builder::vector(fields)}); + } + result_t base_type(const char* tag) { return builder::call("zeek_rt::create_base_type", {builder::id(tag)}); } result_t createZeekType(const hilti::Type& t, const std::optional& id_ = {}) { @@ -1281,8 +1305,7 @@ struct VisitorZeekType : hilti::visitor::PreOrdernamespace_()), - builder::string(id()->local()), builder::vector(fields)}); + return create_record_type(id()->namespace_(), id()->local(), fields); } result_t operator()(const hilti::type::Tuple& t) { @@ -1316,8 +1339,7 @@ struct VisitorZeekType : hilti::visitor::PreOrder(f)), *ztype, builder::bool_(std::get<2>(f))})); } - return builder::call("zeek_rt::create_record_type", {builder::string(id()->namespace_()), - builder::string(id()->local()), builder::vector(fields)}); + return create_record_type(id()->namespace_(), id()->local(), fields); } result_t operator()(const hilti::type::Vector& t) { @@ -1368,7 +1389,12 @@ struct VisitorUnitFields : hilti::visitor::PreOrder { fields.emplace_back(f.id(), f.itemType(), f.isOptional()); } - // TODO: void operator()(const ::spicy::type::unit::item::Switch & f, const position_t p) { + void operator()(const ::spicy::type::unit::item::Switch& f, const position_t p) { + for ( const auto& c : f.cases() ) { + for ( const auto& i : c.items() ) + dispatch(i); + } + } }; } // namespace diff --git a/testing/btest/Baseline/spicy.export-switch/output b/testing/btest/Baseline/spicy.export-switch/output new file mode 100644 index 0000000000..d07e14c539 --- /dev/null +++ b/testing/btest/Baseline/spicy.export-switch/output @@ -0,0 +1,5 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +[foo=12345\x0a] +[foo=ABCDE\x0a] +[foo=67890\x0a] +[foo=FGHIJ\x0a] diff --git a/testing/btest/spicy/export-switch.zeek b/testing/btest/spicy/export-switch.zeek new file mode 100644 index 0000000000..ca08a61743 --- /dev/null +++ b/testing/btest/spicy/export-switch.zeek @@ -0,0 +1,31 @@ +# @TEST-REQUIRES: have-spicy +# +# @TEST-EXEC: spicyz -do test.hlto test.spicy test.evt +# @TEST-EXEC: zeek -Cr ${TRACES}/udp-packet.pcap test.hlto %INPUT >output 2>&1 +# @TEST-EXEC: btest-diff output +# +# @TEST-DOC: Test exporting units with switches. + +event TEST_ZEEK::MessageEvt(message: TEST::Message) + { print message; } + +# @TEST-START-FILE test.spicy +module TEST; + +public type Message = unit { + switch (1) { + * -> foo: bytes &eod; + }; +}; +# @TEST-END-FILE + +# @TEST-START-FILE test.evt +import TEST; +protocol analyzer spicy::Test over UDP: + port 0/udp - 42000/udp, + parse with TEST::Message; + +export TEST::Message; + +on TEST::Message -> event TEST_ZEEK::MessageEvt(self); +# @TEST-END-FILE