[BinPac] ParserBuffer with case not producing correct code

Hi,

binpac parser for flow (flowunit) has probably small bug. In my foo-protocol.pac, I have record like this:

// foo.pac

flow FOO_Flow(is_orig: bool)
{
flowunit = FOO_PDU(is_orig) withcontext(connection, this);
};

// foo-protocol.pac

type FOO_PDU(is_orig: bool) = record {
header: FOO_Header(is_orig);
xbody: case header.flag of {
1 → plain_body: FOO_Body(header);
0 → encrypt_body: Encrypted_Body;
} &length = header.length &requires (header.flag);
} &byteorder = bigendian;

Code that I am getting after binpac parsing is something like this:
FOO_PDU::FOO_PDU(bool is_orig)
{
header_ = 0;
xbody_case_index_ = -1;
plain_body_ = 0;
encrypt_body_ = 0;
buffering_state_ = 0;
buffering_state_ = 0;
is_orig_ = is_orig;
byteorder_ = bigendian;
proc_foo_header_ = 0;
parsing_state_ = 0;
parsing_state_ = 0;
}

bool FOO_PDU::ParseBuffer(flow_buffer_t t_flow_buffer, ContextFOO * t_context)
{

// SOME CODE …
// switch ( parsing_state_ ) {

// … case 0: …

case 1:
{
bool t_header_parsing_complete;
t_header_parsing_complete = false;
while ( ! t_header_parsing_complete && t_flow_buffer->ready() )
{

// SOME MORE CODE

}
if ( ! (t_header_parsing_complete) )
goto need_more_data;
}

// Parse “xbody”
if ( ! xbody_ )
{
}

// SOME MORE CODE here

As you can see, compiler is complaining that error: ‘xbody_’ was not declared in this scope. It is missing in constructor of FOO_PDU. When I checked snmp analyzer, It is doing this process correctly in
int v3Header::Parse(const_byteptr const t_begin_of_data, const_byteptr const t_end_of_data, ContextSNMP * t_context)

  • it does not check for scoped_pdu_data_.

Could you help me to find out what am I doing incorrectly?

Thank you

Martina

One difference is that the xbody field of FOO_PDU has the &length attribute apply to the entire case field. I’d be suspicious that the generated parser has a problem with that. And it may make more sense to instead have each condition of the case use header.length however it needs to. E.g.

type FOO_PDU(is_orig: bool) = record {
  header: FOO_Header(is_orig);
  xbody : case header.flag of {
    1 -> plain_body: FOO_Body(header);
    0 -> encrypt_body: Encrypted_Body(header);
  };
} &byteorder = bigendian;

# I’m just making up the following for demonstration:
type FOO_Body(header: FOO_Header) = record {
  tag: uint8;
  data: bytestring &length = header.length - 1;
};

type Encrypted_Body(header: FOO_Header) = record {
  data: bytestring &length = header.length &transient;
};

- Jon