yhirose / cpp-peglib

A single file C++ header-only PEG (Parsing Expression Grammars) library
MIT License
880 stars 112 forks source link

Segfault using peglint --trace #227

Closed mingodad closed 2 years ago

mingodad commented 2 years ago

When testing the grammar/input shown bellow with peglint --trace I'm getting a segfault at the end:

../../cpp-peglib0/build/lint/peglint --trace c11-lpegrex.peg test.c
E 1*    ┌[chunk] #0
E 1 │┌Sequence #1
E 1 ││┌Repetition #2
...
L 1 │└x Sequence #1
L 1 └x [chunk] #0
Segmentation fault (core dumped)

Input:

int b[2];

Grammar:

# From https://github.com/edubart/lpegrex/blob/main/parsers/c11.lua
# ../../chpeg-chris0/util/chpeg-trace c11-lpegrex.peg test.c
# ../../cpp-peglib0/build/lint/peglint --trace c11-lpegrex.peg test.c

chunk  <-
     SHEBANG  ?  SKIP  translation_unit  (  !  .  )

SHEBANG  <-
     '#!'  (  !  LINEBREAK  .  )  *  LINEBREAK  ?

COMMENT  <-
     LONG_COMMENT
    /  SHRT_COMMENT

LONG_COMMENT  <-
     '/*'  (  !  '*/'  .  )  *  '*/'

SHRT_COMMENT  <-
     '//'  (  !  LINEBREAK  .  )  *  LINEBREAK  ?

DIRECTIVE  <-
     '#'  (  '\\'  LINEBREAK  /  !  LINEBREAK  .  )  *

SKIP  <-
     (  (' ' / '\t' / '\r' / '\n')  +  /  COMMENT  /  DIRECTIVE  /  ( '__extension__' SKIP )  )  *

LINEBREAK  <-
     '\n'  '\r'
    /  '\r'  '\n'
    /  '\n'
    /  '\r'

NAME_SUFFIX  <-
     identifier_suffix

KEYWORD  <-
    ( '_Alignas'
    / '_Alignof'
    / '_Atomic'
    / '_Bool'
    / '_Complex'
    / '_Generic'
    / '_Imaginary'
    / '_Noreturn'
    / '_Static_assert'
    / '_Thread_local'
    / '__asm__'
    / '__asm'
    / '__attribute__'
    / '__attribute'
    / '__extension__'
    / '__inline__'
    / '__inline'
    / '__restrict__'
    / '__restrict'
    / '__thread'
    / '__typeof__'
    / '__volatile__'
    / 'auto'
    / 'break'
    / 'case'
    / 'char'
    / 'const'
    / 'continue'
    / 'default'
    / 'double'
    / 'do'
    / 'else'
    / 'enum'
    / 'extern'
    / 'float'
    / 'for'
    / 'goto'
    / 'if'
    / 'inline'
    / 'int'
    / 'long'
    / 'register'
    / 'restrict'
    / 'return'
    / 'short'
    / 'signed'
    / 'sizeof'
    / 'static'
    / 'struct'
    / 'switch'
    / 'typedef'
    / 'union'
    / 'unsigned'
    / 'void'
    / 'volatile'
    / 'while' ) !NAME_SUFFIX

identifier  <-
     !  KEYWORD  identifier_nondigit  identifier_suffix  ?  SKIP

identifier_suffix  <-
     (  identifier_nondigit  /  digit  )  +

identifier_nondigit  <-
    [a-zA-Z_]
    /  universal_character_name

digit  <-
    [0-9]

universal_character_name  <-
     '\\u'  hex_quad
    /  '\\U'  hex_quad

hex_quad  <-
     hexadecimal_digit

constant  <-
     (  floating_constant  /  integer_constant  /  enumeration_constant  /  character_constant  )  SKIP

integer_constant  <-
     octal_constant  integer_suffix  ?
    /  hexadecimal_constant  integer_suffix  ?
    /  decimal_constant  integer_suffix  ?

decimal_constant  <-
     digit  +

octal_constant  <-
     '0'  octal_digit  +

hexadecimal_constant  <-
     hexadecimal_prefix  hexadecimal_digit  +

hexadecimal_prefix  <-
     '0' [xX]

octal_digit  <-
    [0-7]

hexadecimal_digit  <-
    [0-9a-fA-F]

integer_suffix  <-
     unsigned_suffix  (  long_long_suffix  /  long_suffix  )  ?
    /  (  long_long_suffix  /  long_suffix  )  unsigned_suffix  ?

unsigned_suffix  <-
    [uU]

long_suffix  <-
    [lL]

long_long_suffix  <-
     'll'
    /  'LL'

floating_constant  <-
     decimal_floating_constant
    /  hexadecimal_floating_constant

decimal_floating_constant  <-
     (  fractional_constant  exponent_part  ?  /  digit_sequence  exponent_part  )  floating_suffix  ?

hexadecimal_floating_constant  <-
     hexadecimal_prefix  (  hexadecimal_fractional_constant  /  hexadecimal_digit_sequence  )  binary_exponent_part  floating_suffix  ?

fractional_constant  <-
     digit_sequence  ?  '.'  digit_sequence
    /  digit_sequence  '.'

exponent_part  <-
    [eE] sign  ?  digit_sequence

sign  <-
    [+-]

digit_sequence  <-
     digit  +

hexadecimal_fractional_constant  <-
     hexadecimal_digit_sequence  ?  '.'  hexadecimal_digit_sequence
    /  hexadecimal_digit_sequence  '.'

binary_exponent_part  <-
    [pP] sign  ?  digit_sequence

hexadecimal_digit_sequence  <-
     hexadecimal_digit  +

floating_suffix  <-
    [flFL]

enumeration_constant  <-
     identifier

character_constant  <-
     "'"  c_char_sequence  "'"
    /  "L'"  c_char_sequence  "'"
    /  "u'"  c_char_sequence  "'"
    /  "U'"  c_char_sequence  "'"

c_char_sequence  <-
     c_char  +

c_char  <-
    [^'\\\n\r]
    /  escape_sequence

escape_sequence  <-
     simple_escape_sequence
    /  octal_escape_sequence
    /  hexadecimal_escape_sequence
    /  universal_character_name

simple_escape_sequence  <-
     "\\'"
    /  '\\"'
    /  "\\?"
    /  "\\\\"
    /  "\\a"
    /  "\\b"
    /  "\\f"
    /  "\\n"
    /  "\\r"
    /  "\\t"
    /  "\\v"

octal_escape_sequence  <-
     '\\'  octal_digit

hexadecimal_escape_sequence  <-
     '\\x'  hexadecimal_digit  +

string_literal  <-
     encoding_prefix  ?  string_suffix  +

string_suffix  <-
     '"'  s_char_sequence  ?  '"'  SKIP

encoding_prefix  <-
     'u8'
    /  'u'
    /  'U'
    /  'L'

s_char_sequence  <-
     s_char  +

s_char  <-
    [^"\\\n\r]
    /  escape_sequence

primary_expression  <-
     type_name
    /  identifier
    /  constant
    /  string_literal
    /  statement_expression
    /  ( '(' SKIP )  expression  ( ')' SKIP )
    /  generic_selection

statement_expression  <-
     '({'  SKIP  (  declaration  /  statement  )  *  '})'  SKIP

generic_selection  <-
     ( '_Generic' SKIP )  ( '(' SKIP )  assignment_expression  ( ',' SKIP )  generic_assoc_list  ( ')' SKIP )

generic_assoc_list  <-
     generic_association  (  ( ',' SKIP )  generic_association  )  *

generic_association  <-
     type_name  ( ':' SKIP )  assignment_expression
    /  ( 'default' SKIP )  ( ':' SKIP )  assignment_expression

postfix_expression  <-
     (  postfix_expression_prefix  postfix_expression_suffix  *  )

postfix_expression_prefix  <-
     (  type_initializer  /  primary_expression  )

type_initializer  <-
     ( '(' SKIP )  type_name  ( ')' SKIP )  ( '{' SKIP )  initializer_list  ?  ( ',' SKIP )  ?  ( '}' SKIP )

postfix_expression_suffix  <-
     array_subscript
    /  argument_expression
    /  struct_or_union_member
    /  pointer_member
    /  post_increment
    /  post_decrement

array_subscript  <-
     ( '[' SKIP )  expression  ( ']' SKIP )

argument_expression  <-
     ( '(' SKIP )  argument_expression_list  ?  ( ')' SKIP )

struct_or_union_member  <-
     ( '.' SKIP )  identifier

pointer_member  <-
     ( '->' SKIP )  identifier

post_increment  <-
     ( '++' SKIP )

post_decrement  <-
     ( '--' SKIP )

argument_expression_list  <-
     assignment_expression  (  ( ',' SKIP )  assignment_expression  )  *

unary_expression  <-
     unary_op
    /  postfix_expression

unary_op  <-
     (  ( '++' SKIP )  /  ( '--' SKIP )  )  unary_expression
    /  (  ( 'sizeof' SKIP )  )  unary_expression
    /  (  ( '&' SKIP )  /  ( '+' SKIP )  /  ( '-' SKIP )  /  ( '~' SKIP )  /  ( '!' SKIP )  )  cast_expression
    /  ( '*' SKIP )  cast_expression
    /  (  ( 'sizeof' SKIP )  /  ( '_Alignof' SKIP )  )  ( '(' SKIP )  type_name  ( ')' SKIP )

cast_expression  <-
     op_cast
    /  unary_expression

op_cast  <-
     ( '(' SKIP )  'cast'  type_name  ( ')' SKIP )  cast_expression

multiplicative_expression  <-
     (  cast_expression  op_multiplicative  *  )

op_multiplicative  <-
     (  ( '/' SKIP )  /  ( '%' SKIP )  )  cast_expression
    /  ( '*' SKIP )  cast_expression

additive_expression  <-
     (  multiplicative_expression  op_additive  *  )

op_additive  <-
     (  ( '+' SKIP )  /  ( '-' SKIP )  )  multiplicative_expression

shift_expression  <-
     (  additive_expression  op_shift  *  )

op_shift  <-
     (  ( '<<' SKIP )  /  ( '>>' SKIP )  )  additive_expression

relational_expression  <-
     (  shift_expression  op_relational  *  )

op_relational  <-
     (  ( '<=' SKIP )  /  ( '>=' SKIP )  /  ( '<' SKIP )  /  ( '>' SKIP )  )  shift_expression

equality_expression  <-
     (  relational_expression  op_equality  *  )

op_equality  <-
     (  ( '==' SKIP )  /  ( '!=' SKIP )  )  relational_expression

AND_expression  <-
     (  equality_expression  op_AND  *  )

op_AND  <-
     ( '&' SKIP )  equality_expression

exclusive_OR_expression  <-
     (  AND_expression  op_OR  *  )

op_OR  <-
     ( '^' SKIP )  AND_expression

inclusive_OR_expression  <-
     (  exclusive_OR_expression  op_inclusive_OR  *  )

op_inclusive_OR  <-
     ( '|' SKIP )  exclusive_OR_expression

logical_AND_expression  <-
     (  inclusive_OR_expression  op_logical_AND  *  )

op_logical_AND  <-
     '&&'  SKIP  inclusive_OR_expression

logical_OR_expression  <-
     (  logical_AND_expression  op_logical_OR  *  )

op_logical_OR  <-
     ( '||' SKIP )  logical_AND_expression

conditional_expression  <-
     (  logical_OR_expression  op_conditional  ?  )

op_conditional  <-
     ( '?' SKIP )  expression  ( ':' SKIP )  conditional_expression

op_assignment  <-
     unary_expression  assignment_operator  assignment_expression

assignment_expression  <-
     op_assignment
    /  conditional_expression

assignment_operator  <-
     ( '=' SKIP )
    /  ( '*=' SKIP )
    /  ( '/=' SKIP )
    /  ( '%=' SKIP )
    /  ( '+=' SKIP )
    /  ( '-=' SKIP )
    /  ( '<<=' SKIP )
    /  ( '>>=' SKIP )
    /  ( '&=' SKIP )
    /  ( '^=' SKIP )
    /  ( '|=' SKIP )

expression  <-
     assignment_expression  (  ( ',' SKIP )  assignment_expression  )  *

constant_expression  <-
     conditional_expression

declaration  <-
     (  typedef_declaration  /  type_declaration  /  static_assert_declaration  )  ( ';' SKIP )

extension_specifiers  <-
     extension_specifier  +

extension_specifier  <-
     attribute
    /  asm
    /  extension

attribute  <-
     (  ( '__attribute__' SKIP )  /  ( '__attribute' SKIP )  )  ( '(' SKIP )  ( '(' SKIP )  attribute_list  ( ')' SKIP )  ( ')' SKIP )

attribute_list  <-
     attribute_item  (  ( ',' SKIP )  attribute_item  )  *

attribute_item  <-
     identifier  (  ( '(' SKIP )  expression  (  ( ',' SKIP )  expression  )  *  ( ')' SKIP )  )  ?

asm  <-
     (  ( '__asm' SKIP )  /  ( '__asm__' SKIP )  )  (  ( '__volatile__' SKIP )  /  ( 'volatile' SKIP )  )  ?  ( '(' SKIP )  asm_argument  (  ( ',' SKIP )  asm_argument  )  *  ( ')' SKIP )

asm_argument  <-
     (  string_literal  /  ( ':' SKIP )  /  expression  )  +

extension  <-
     ( '__extension__' SKIP )

typedef_declaration  <-
     ( 'typedef' SKIP )  declaration_specifiers  (  typedef_declarator  (  ( ',' SKIP )  typedef_declarator  )  *  )  ?

type_declaration  <-
     declaration_specifiers  init_declarator_list  ?

declaration_specifiers  <-
     (  storage_class_specifier  /  type_specifier  /  type_qualifier  /  function_specifier  /  alignment_specifier  )  +

init_declarator_list  <-
     init_declarator  (  ( ',' SKIP )  init_declarator  )  *

init_declarator  <-
     declarator  (  ( '=' SKIP )  initializer  )  ?

storage_class_specifier  <-
     ( 'extern' SKIP )
    /  ( 'static' SKIP )
    /  ( '_Thread_local' SKIP )
    /  ( 'auto' SKIP )
    /  ( 'register' SKIP )
    /  ( '__thread' SKIP )

type_specifier  <-
     ( 'void' SKIP )
    /  ( 'char' SKIP )
    /  ( 'short' SKIP )
    /  ( 'int' SKIP )
    /  ( 'long' SKIP )
    /  ( 'float' SKIP )
    /  ( 'double' SKIP )
    /  ( 'signed' SKIP )
    /  ( 'unsigned' SKIP )
    /  ( '_Bool' SKIP )
    /  ( '_Complex' SKIP )
    /  ( '_Imaginary' SKIP )
    /  atomic_type_specifier
    /  struct_or_union_specifier
    /  enum_specifier
    /  typedef_name
    /  typeof

struct_or_union_specifier  <-
     struct_or_union  extension_specifiers  ?  identifier  ?  (  ( '{' SKIP )  struct_declaration_list  ?  ( '}' SKIP )  )  ?

struct_or_union  <-
     ( 'struct' SKIP )
    /  ( 'union' SKIP )

struct_declaration_list  <-
     (  struct_declaration  /  static_assert_declaration  )  +

struct_declaration  <-
     specifier_qualifier_list  struct_declarator_list  ?  ( ';' SKIP )

specifier_qualifier_list  <-
     (  type_specifier  /  type_qualifier  )  +

struct_declarator_list  <-
     struct_declarator  (  ( ',' SKIP )  struct_declarator  )  *

struct_declarator  <-
     declarator  (  ( ':' SKIP )  constant_expression  )  ?
    /  ( ':' SKIP )  #false
        constant_expression

enum_specifier  <-
     ( 'enum' SKIP )  (  identifier  ?  ( '{' SKIP )  enumerator_list  ( ',' SKIP )  ?  ( '}' SKIP )  /  identifier  )

enumerator_list  <-
     enumerator  (  ( ',' SKIP )  enumerator  )  *

enumerator  <-
     enumeration_constant  (  ( '=' SKIP )  constant_expression  )  ?

atomic_type_specifier  <-
     ( '_Atomic' SKIP )  ( '(' SKIP )  type_name  ( ')' SKIP )

type_qualifier  <-
     ( 'const' SKIP )
    /  ( 'restrict' SKIP )
    /  (  ( '__restrict' SKIP )  /  ( '__restrict__' SKIP )  )
    /  ( 'volatile' SKIP )
    /  ( '_Atomic' SKIP )
    /  extension_specifier

function_specifier  <-
     ( 'inline' SKIP )
    /  (  ( '__inline' SKIP )  /  ( '__inline__' SKIP )  )
    /  ( '_Noreturn' SKIP )

alignment_specifier  <-
     ( '_Alignas' SKIP )  ( '(' SKIP )  type_name  ( ')' SKIP )
    /  ( '_Alignas' SKIP )  ( '(' SKIP )  constant_expression  ( ')' SKIP )

declarator  <-
     (  pointer  *  direct_declarator  )  extension_specifiers  ?

typedef_declarator  <-
     (  pointer  *  typedef_direct_declarator  )  extension_specifiers  ?

direct_declarator  <-
     (  (  identifier  /  ( '(' SKIP )  declarator  ( ')' SKIP )  )  direct_declarator_suffix  *  )

typedef_direct_declarator  <-
     (  (  typedef_identifier  /  ( '(' SKIP )  typedef_declarator  ( ')' SKIP )  )  direct_declarator_suffix  *  )

direct_declarator_suffix  <-
     declarator_subscript
    /  declarator_parameters

declarator_subscript  <-
     ( '[' SKIP )  type_qualifier_list  ?  assignment_expression  ?  ( ']' SKIP )
    /  ( '[' SKIP )  &  ( 'static' SKIP )  storage_class_specifier  type_qualifier_list  ?  assignment_expression  ( ']' SKIP )
    /  ( '[' SKIP )  type_qualifier_list  &  ( 'static' SKIP )  storage_class_specifier  assignment_expression  ( ']' SKIP )
    /  ( '[' SKIP )  type_qualifier_list  ?  pointer  ( ']' SKIP )

declarator_parameters  <-
     ( '(' SKIP )  parameter_type_list  ( ')' SKIP )
    /  ( '(' SKIP )  identifier_list  ?  ( ')' SKIP )

pointer  <-
     ( '*' SKIP )  type_qualifier_list  ?

type_qualifier_list  <-
     type_qualifier  +

parameter_type_list  <-
     parameter_list  (  ( ',' SKIP )  parameter_varargs  )  ?

parameter_varargs  <-
     ( '...' SKIP )

parameter_list  <-
     parameter_declaration  (  ( ',' SKIP )  parameter_declaration  )  *

parameter_declaration  <-
     declaration_specifiers  (  declarator  /  abstract_declarator  ?  )

identifier_list  <-
     identifier  (  ( ',' SKIP )  identifier  )  *

type_name  <-
     specifier_qualifier_list  +  abstract_declarator  ?
    /  typeof

typeof  <-
     ( '__typeof__' SKIP )  argument_expression

abstract_declarator  <-
     (  (  pointer  +  direct_abstract_declarator  ?  )  /  direct_abstract_declarator  )  extension_specifiers  ?

direct_abstract_declarator  <-
     (  ( '(' SKIP )  abstract_declarator  ( ')' SKIP )  direct_declarator_suffix  *  /  direct_declarator_suffix  +  )

typedef_name  <-
     &  (  identifier  )  identifier

typedef_identifier  <-
     &  (  identifier  )  identifier

initializer  <-
     assignment_expression
    /  ( '{' SKIP )  initializer_list  ?  ( ',' SKIP )  ?  ( '}' SKIP )

initializer_list  <-
     initializer_item  (  ( ',' SKIP )  initializer_item  )  *

initializer_item  <-
     designation
    /  initializer

designation  <-
     designator_list  ( '=' SKIP )  initializer

designator_list  <-
     designator  +

designator  <-
     subscript_designator
    /  member_designator

subscript_designator  <-
     ( '[' SKIP )  constant_expression  ( ']' SKIP )

member_designator  <-
     ( '.' SKIP )  identifier

static_assert_declaration  <-
     ( '_Static_assert' SKIP )  ( '(' SKIP )  constant_expression  ( ',' SKIP )  string_literal  ( ')' SKIP )

statement  <-
     label_statement
    /  case_statement
    /  default_statement
    /  compound_statement
    /  expression_statement
    /  if_statement
    /  switch_statement
    /  while_statement
    /  do_while_statement
    /  for_statement
    /  goto_statement
    /  continue_statement
    /  break_statement
    /  return_statement
    /  asm_statement
    /  ( ';' SKIP )

label_statement  <-
     identifier  ( ':' SKIP )

case_statement  <-
     ( 'case' SKIP )  constant_expression  ( ':' SKIP )  statement  ?

default_statement  <-
     ( 'default' SKIP )  ( ':' SKIP )  statement  ?

compound_statement  <-
     ( '{' SKIP )  (  label_statement  /  declaration  /  statement  )  *  ( '}' SKIP )

expression_statement  <-
     expression  ( ';' SKIP )

if_statement  <-
     ( 'if' SKIP )  ( '(' SKIP )  expression  ( ')' SKIP )  statement  (  ( 'else' SKIP )  statement  )  ?

switch_statement  <-
     ( 'switch' SKIP )  ( '(' SKIP )  expression  ( ')' SKIP )  statement

while_statement  <-
     ( 'while' SKIP )  ( '(' SKIP )  expression  ( ')' SKIP )  statement

do_while_statement  <-
     ( 'do' SKIP )  statement  ( 'while' SKIP )  ( '(' SKIP )  expression  ( ')' SKIP )  ( ';' SKIP )

for_statement  <-
     ( 'for' SKIP )  ( '(' SKIP )  (  declaration  /  expression  ?  ( ';' SKIP )  )  expression  ?  ( ';' SKIP )  expression  ?  ( ')' SKIP )  statement

goto_statement  <-
     ( 'goto' SKIP )  constant_expression  ( ';' SKIP )

continue_statement  <-
     ( 'continue' SKIP )  ( ';' SKIP )

break_statement  <-
     ( 'break' SKIP )  ( ';' SKIP )

return_statement  <-
     ( 'return' SKIP )  expression  ?  ( ';' SKIP )

asm_statement  <-
     asm  ( ';' SKIP )

translation_unit  <-
     external_declaration  *

external_declaration  <-
     function_definition
    /  declaration
    /  ( ';' SKIP )

function_definition  <-
     declaration_specifiers  declarator  declaration_list  compound_statement

declaration_list  <-
     declaration  *
mingodad commented 2 years ago

Valgrind output:

==1967== Invalid read of size 8
==1967==    at 0x113C10: std::_Function_base::_M_empty() const (in cpp-peglib0/build/lint/peglint)
==1967==    by 0x144D45: std::function<void (unsigned long, unsigned long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>::operator bool() const (in cpp-peglib0/build/lint/peglint)
==1967==    by 0x13CB39: peg::parser::post_process(char const*, unsigned long, peg::Definition::Result const&) const (in cpp-peglib0/build/lint/peglint)
==1967==    by 0x13C8BC: peg::parser::parse_n(char const*, unsigned long, char const*) const (in cpp-peglib0/build/lint/peglint)
==1967==    by 0x112D51: main (in cpp-peglib0/build/lint/peglint)
==1967==  Address 0x10 is not stack'd, malloc'd or (recently) free'd
==1967== 
==1967== 
==1967== Process terminating with default action of signal 11 (SIGSEGV)
==1967==  Access not within mapped region at address 0x10
==1967==    at 0x113C10: std::_Function_base::_M_empty() const (in cpp-peglib0/build/lint/peglint)
==1967==    by 0x144D45: std::function<void (unsigned long, unsigned long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>::operator bool() const (in cpp-peglib0/build/lint/peglint)
==1967==    by 0x13CB39: peg::parser::post_process(char const*, unsigned long, peg::Definition::Result const&) const (in cpp-peglib0/build/lint/peglint)
==1967==    by 0x13C8BC: peg::parser::parse_n(char const*, unsigned long, char const*) const (in cpp-peglib0/build/lint/peglint)
==1967==    by 0x112D51: main (in cpp-peglib0/build/lint/peglint)
==1967==  If you believe this happened as a result of a stack
==1967==  overflow in your program's main thread (unlikely but
==1967==  possible), you can try to increase the size of the
==1967==  main thread stack using the --main-stacksize= flag.
==1967==  The main thread stack size used in this run was 8388608.
==1967== 
==1967== HEAP SUMMARY:
==1967==     in use at exit: 380,274 bytes in 3,790 blocks
==1967==   total heap usage: 30,722 allocs, 26,932 frees, 1,539,374 bytes allocated
==1967== 
==1967== LEAK SUMMARY:
==1967==    definitely lost: 0 bytes in 0 blocks
==1967==    indirectly lost: 0 bytes in 0 blocks
==1967==      possibly lost: 0 bytes in 0 blocks
==1967==    still reachable: 380,274 bytes in 3,790 blocks
==1967==         suppressed: 0 bytes in 0 blocks
==1967== Rerun with --leak-check=full to see details of leaked memory
==1967== 
==1967== For lists of detected and suppressed errors, rerun with: -s
==1967== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
yhirose commented 2 years ago

@mingodad, thank you for the report. Could you narrow down the scope and find the smallest possible grammar revealing the segfault problem? Thanks!

yhirose commented 2 years ago

@mingodad, I just tried it with peglint and on the playground. Both worked fine.

E 1 ┌[chunk] #0
E 1 │┌Sequence #1
...
L 1 │└x Sequence #1
L 1 └x [chunk] #0
bug.txt:1:6: syntax error, unexpected '[', expecting ';'.
image