ragel
ragel copied to clipboard
ragel 6.10 segfault
Hi,
When I generate C++ sources via command line :
ragel ServerBinaryControlParser.rl -o ServerBinaryControlParser.cc
it segfaults. When I see the generated graph (ragel ServerBinaryControlParser.rl -p -V > /tmp/my.gv
) it seems ok. When I change the line m_destination
(commented), then it generates C++ sources right again (but I think my original grammar is correct).
The sources, slightly minimized can be found below.
Binary.rl
%%{
machine binary;
action mark {}
action record_client_id {}
action push_len {}
action reset_len {}
action has_more {}
###########################
# message related actions #
###########################
action push_arr_len { }
action reset_arr_len { }
action has_more_arr {}
action param_name {}
action param_type {}
action param_text { param_value = Consume();}
action move_bool { }
action move_s8 { }
action move_u8 { }
action move_s16 { }
action move_u16 { }
action move_s32 { }
action move_u32 { }
action move_s64 { }
action move_u64 { }
action move_f32 { }
action move_f64 { }
action move_text { }
action move_binary { }
action reset_param { }
action add_u8 { }
action add_s8 { }
action add_u16 { }
action add_s16 { }
action add_u32 { }
action add_s32 { }
action add_u64 { }
action add_s64 { }
action add_f32 { }
action add_f64 { }
action push_bool { }
action push_s8 { }
action push_u8 { }
action push_s16 { }
action push_u16 { }
action push_s32 { }
action push_u32 { }
action push_s64 { }
action push_u64 { }
action push_f32 { }
action push_f64 { }
action reset_a_bool { }
action reset_a_s8 { }
action reset_a_u8 { }
action reset_a_s16 { }
action reset_a_u16 { }
action reset_a_s32 { }
action reset_a_u32 { }
action reset_a_s64 { }
action reset_a_u64 { }
action reset_a_f32 { }
action reset_a_f64 { }
action move_a_bool {}
action move_a_s8 { }
action move_a_u8 { }
action move_a_s16 { }
action move_a_u16 { }
action move_a_s32 { }
action move_a_u32 { }
action move_a_s64 { }
action move_a_u64 { }
action move_a_f32 { }
action move_a_f64 { }
t_connect = /connect/i;
t_protocol = /protocol/i;
t_binary = /binary/i;
t_console = /console/i;
t_ok = 0x00 0x4F 0x4B 0x00;
t_error = 0x01 0x45 0x52 0x52;
t_accepted = 0x00 0x41 0x43 0x43;
t_rejected = 0x00 0x52 0x45 0x4A;
t_pending = 0x00 0x50 0x45 0x4E;
t_end = 0x00 0x45 0x4E 0x44;
t_sync = 0x53 0x59 0x4E 0x43;
t_heartbeat = 0x00 0x48 0x45 0x41;
t_notification = 0x01 0x4E 0x54 0x46;
t_message = 0x00 0x4D 0x45 0x53;
t_data = 0x01 0x44 0x41 0x54;
t_command = 0x01 0x43 0x4F 0x4D;
t_query = 0x01 0x51 0x55 0x45;
string_len = any{2} >reset_len $push_len;
string = (any when has_more )** >mark;
arr_len = any{2} >reset_arr_len $push_arr_len;
param_bool = (0x00 | 0x01) >reset_param $add_u8;
param_num_s8 = any{1} >reset_param $add_s8 ;
param_num_u8 = any{1} >reset_param $add_u8 ;
param_num_s16 = any{2} >reset_param $add_s16;
param_num_u16 = any{2} >reset_param $add_u16;
param_num_s32 = any{4} >reset_param $add_s32;
param_num_u32 = any{4} >reset_param $add_u32;
param_num_s64 = any{8} >reset_param $add_s64;
param_num_u64 = any{8} >reset_param $add_u64;
param_num_f32 = any{4} >reset_param $add_f32;
param_num_f64 = any{8} >reset_param $add_f64;
param_value_b = 0x01 0x00 'B' <: param_bool %move_bool;
param_value_s8 = 0x02 0x00 'S8' <: param_num_s8 %move_s8 ;
param_value_u8 = 0x02 0x00 'U8' <: param_num_u8 %move_u8 ;
param_value_s16 = 0x03 0x00 'S16' <: param_num_s16 %move_s16;
param_value_u16 = 0x03 0x00 'U16' <: param_num_u16 %move_u16;
param_value_s32 = 0x03 0x00 'S32' <: param_num_s32 %move_s32;
param_value_u32 = 0x03 0x00 'U32' <: param_num_u32 %move_u32;
param_value_s64 = 0x03 0x00 'S64' <: param_num_s64 %move_s64;
param_value_u64 = 0x03 0x00 'U64' <: param_num_u64 %move_u64;
param_value_f32 = 0x03 0x00 'F32' <: param_num_f32 %move_f32;
param_value_f64 = 0x03 0x00 'F64' <: param_num_f64 %move_f64;
param_arr_b = 0x02 0x00 'B*' <: arr_len (param_bool @{++arr_raw_counter;} %push_bool when has_more_arr)** >reset_a_bool %move_a_bool;
param_arr_s8 = 0x03 0x00 'S8*' <: arr_len (param_num_s8 @{++arr_raw_counter;} %push_s8 when has_more_arr)** >reset_a_s8 %move_a_s8 ;
param_arr_u8 = 0x03 0x00 'U8*' <: arr_len (param_num_u8 @{++arr_raw_counter;} %push_u8 when has_more_arr)** >reset_a_u8 %move_a_u8 ;
param_arr_s16 = 0x04 0x00 'S16*' <: arr_len (param_num_s16 @{++arr_raw_counter;} %push_s16 when has_more_arr)* >reset_a_s16 %move_a_s16 ;
param_arr_u16 = 0x04 0x00 'U16*' <: arr_len (param_num_u16 @{++arr_raw_counter;} %push_u16 when has_more_arr)** >reset_a_u16 %move_a_u16 ;
param_arr_s32 = 0x04 0x00 'S32*' <: arr_len (param_num_s32 @{++arr_raw_counter;} %push_s32 when has_more_arr)** >reset_a_s32 %move_a_s32 ;
param_arr_u32 = 0x04 0x00 'U32*' <: arr_len (param_num_u32 @{++arr_raw_counter;} %push_u32 when has_more_arr)** >reset_a_u32 %move_a_u32 ;
param_arr_s64 = 0x04 0x00 'S64*' <: arr_len (param_num_s64 @{++arr_raw_counter;} %push_s64 when has_more_arr)** >reset_a_s64 %move_a_s64 ;
param_arr_u64 = 0x04 0x00 'U64*' <: arr_len (param_num_u64 @{++arr_raw_counter;} %push_u64 when has_more_arr)** >reset_a_u64 %move_a_u64 ;
param_arr_f32 = 0x04 0x00 'F32*' <: arr_len (param_num_f32 @{++arr_raw_counter;} %push_f32 when has_more_arr)** >reset_a_f32 %move_a_f32 ;
param_arr_f64 = 0x04 0x00 'F64*' <: arr_len (param_num_f64 @{++arr_raw_counter;} %push_f64 when has_more_arr)** >reset_a_f64 %move_a_f64 ;
param_scalar_value = param_value_b
| param_value_s8 | param_value_u8
| param_value_s16 | param_value_u16
| param_value_s32 | param_value_u32
| param_value_s64 | param_value_u64
| param_value_f32 | param_value_f64
;
param_array_value = param_arr_b
| param_arr_s8 | param_arr_u8
| param_arr_s16 | param_arr_u16
| param_arr_s32 | param_arr_u32
| param_arr_s64 | param_arr_u64
| param_arr_f32 | param_arr_f64
;
param_text_type = '=' string_len <: string %param_type;
param_text = param_text_type <: string_len <: string %param_text %move_text;
param_binary_type = '$' string_len <: string %param_type;
param_binary = param_binary_type <: string_len <: string %param_text %move_binary;
param_value = param_scalar_value | param_array_value;
param_name = string_len <: string %param_name;
param_fixed = '@' <: param_name <: param_value;
param_dynamic = '#' <: param_name <: (param_text | param_binary);
param = param_fixed | param_dynamic;
mesage_body = param**;
}%%
ServerBinaryControlParser.rl
%%{
machine binary_server_parser;
include binary "Binary.rl";
action done { }
action push_heartbeat { }
action push_cmd_register { }
action push_cmd_subscribe { }
action push_message { }
action role_add { }
action role_remove { }
action subs_add { }
action subs_remove { }
action record_role { }
action record_dest_role { }
action record_dest_client { }
action record_dest_bc { }
action record_delivery_all { }
action record_delivery_no { }
action record_delivery_any { }
action record_message_name { }
action push_q_role_list { }
action push_q_client_list { }
action push_q_client_list_roles { }
action push_q_clients_with_roles { }
cmd_role_add = 0x03 0x00 'add' <: string_len string %role_add;
cmd_role_remove = 0x06 0x00 'remove' <: string_len string %role_remove;
cmd_header_role = '>' <: (cmd_role_add | cmd_role_remove);
cmd_register = t_command 0x0D 0x00 'ROLE-REGISTER' <: cmd_header_role** %push_cmd_register;
cmd_subs_add = 0x03 0x00 'add' <: string_len string %subs_add;
cmd_subs_remove = 0x06 0x00 'remove' <: string_len string %subs_remove;
cmd_header_subs = '>' <: (cmd_subs_add | cmd_subs_remove);
cmd_subscribe = t_command <: 0x0E <: 0x00 <: 'ROLE-SUBSCRIBE' <: cmd_header_subs** %push_cmd_subscribe;
delivery_all = 0x00 %record_delivery_all;
delivery_no = 0xFF %record_delivery_no;
delivery_any = 0x01 %record_delivery_any;
single_dest = string_len <: (('@' <: string >mark %record_dest_role ) | string %record_dest_client);
m_delivery = (delivery_all | delivery_no | delivery_any);
m_broadcast = 0xFF 0xFF %record_dest_bc;
#m_destination = m_broadcast | ((arr_len -- m_broadcast) <: single_dest single_dest**);
m_destination = m_broadcast | ((arr_len) single_dest single_dest**);
m_name = t_data string_len <: string %record_message_name;
client_id = string_len string %record_client_id;
client_role = string_len string %record_role;
q_h_client_id = '>' 0x02 0x00 'id' <: client_id;
q_h_role = '>' 0x04 0x00 'role' client_role;
q_role_list = 0x09 0x00 <: 'ROLE-LIST' %push_q_role_list;
q_client_list = 0x0A 0x00 <: 'CLIENT-LIST' %push_q_client_list;
q_client_list_roles = 0x11 0x00 <: 'CLIENT-LIST-ROLES' <: q_h_client_id %push_q_client_list_roles;
q_clients_with_roles = 0x11 0x00 <: 'CLIENTS-WITH-ROLE' <: q_h_role %push_q_clients_with_roles;
query_body = q_role_list | q_client_list | q_client_list_roles | q_clients_with_roles;
cmd_body = cmd_register | cmd_subscribe;
command = cmd_body <: t_end;
query = t_query <: query_body <: t_end;
heartbeat = t_heartbeat %push_heartbeat;
message = t_message m_delivery <: m_destination <: t_end <: m_name <: mesage_body %push_message <: t_end;
start := t_sync (heartbeat | command | query | message) @done;
}%%
#include <cmath>
#include "ServerBinaryControlParser.hpp"
namespace stheno::proto::parser {
using namespace stheno::proto::protocol;
%% write data;
ServerBinaryControlParser::ServerBinaryControlParser() noexcept {
Reset();
}
size_t ServerBinaryControlParser::Parse(const std::string_view& data) noexcept {
pb = data.data();
pe = pb + data.length();
p = pb;
eof = pe;
%% write exec;
return p - pb;
}
bool ServerBinaryControlParser::Success() noexcept {
return cs >= binary_server_parser_first_final;
}
void ServerBinaryControlParser::Reset() noexcept {
state = State::NONE;
cs = binary_server_parser_en_start;
}
}