Merge remote-tracking branch 'origin/topic/robin/gh-3157-export-switch'

* origin/topic/robin/gh-3157-export-switch:
  [Spicy] Support `switch` fields when exporting Spicy types to Zeek.

(cherry picked from commit cd2c193cb2)
This commit is contained in:
Robin Sommer 2023-07-07 11:45:53 +02:00 committed by Tim Wojtulewicz
parent 4ae02b7973
commit ddaa553418
3 changed files with 70 additions and 8 deletions

View file

@ -1173,7 +1173,7 @@ bool GlueCompiler::CreateSpicyHook(glue::Event* ev) {
} }
namespace { 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. // HILTI type.
// //
// Note: Any logic changes here must be reflected in the plugin driver's // Note: Any logic changes here must be reflected in the plugin driver's
@ -1194,6 +1194,30 @@ struct VisitorZeekType : hilti::visitor::PreOrder<hilti::Result<hilti::Expressio
return (! ids.empty() && ids.front().has_value()) ? ids.front()->namespace_() : hilti::ID(); return (! ids.empty() && ids.front().has_value()) ? ids.front()->namespace_() : hilti::ID();
} }
result_t create_record_type(const hilti::ID& ns, const hilti::ID& local,
const std::vector<hilti::Expression>& 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<hilti::expression::Ctor>()
.ctor()
.as<hilti::ctor::Tuple>()
.value()[0]
.as<hilti::expression::Ctor>()
.ctor()
.as<hilti::ctor::String>()
.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 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<hilti::ID>& id_ = {}) { result_t createZeekType(const hilti::Type& t, const std::optional<hilti::ID>& id_ = {}) {
@ -1281,8 +1305,7 @@ struct VisitorZeekType : hilti::visitor::PreOrder<hilti::Result<hilti::Expressio
fields.emplace_back(builder::tuple({builder::string(f.id()), *ztype, builder::bool_(f.isOptional())})); fields.emplace_back(builder::tuple({builder::string(f.id()), *ztype, builder::bool_(f.isOptional())}));
} }
return builder::call("zeek_rt::create_record_type", {builder::string(id()->namespace_()), return create_record_type(id()->namespace_(), id()->local(), fields);
builder::string(id()->local()), builder::vector(fields)});
} }
result_t operator()(const hilti::type::Tuple& t) { result_t operator()(const hilti::type::Tuple& t) {
@ -1316,8 +1339,7 @@ struct VisitorZeekType : hilti::visitor::PreOrder<hilti::Result<hilti::Expressio
ns = namespace_(); ns = namespace_();
} }
return builder::call("zeek_rt::create_record_type", return create_record_type(ns, local, fields);
{builder::string(ns), builder::string(local), builder::vector(fields)});
} }
result_t operator()(const ::spicy::type::Unit& t) { result_t operator()(const ::spicy::type::Unit& t) {
@ -1333,8 +1355,7 @@ struct VisitorZeekType : hilti::visitor::PreOrder<hilti::Result<hilti::Expressio
builder::tuple({builder::string(std::get<0>(f)), *ztype, builder::bool_(std::get<2>(f))})); builder::tuple({builder::string(std::get<0>(f)), *ztype, builder::bool_(std::get<2>(f))}));
} }
return builder::call("zeek_rt::create_record_type", {builder::string(id()->namespace_()), return create_record_type(id()->namespace_(), id()->local(), fields);
builder::string(id()->local()), builder::vector(fields)});
} }
result_t operator()(const hilti::type::Vector& t) { result_t operator()(const hilti::type::Vector& t) {
@ -1368,7 +1389,12 @@ struct VisitorUnitFields : hilti::visitor::PreOrder<void, VisitorUnitFields> {
fields.emplace_back(f.id(), f.itemType(), f.isOptional()); 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 } // namespace

View file

@ -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]

View file

@ -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