c++: fix double free when a symbol_type was moved

Currently the following piece of code crashes (with parse.assert),
because we don't record that s was moved-from, and we invoke its dtor.

    {
      auto s = parser::make_INT (42);
      auto s2 = std::move (s);
    }

Reported by Wolfgang Thaller.
http://lists.gnu.org/archive/html/bug-bison/2018-12/msg00077.html

* data/c++.m4 (by_type): Provide a move-ctor.
(basic_symbol): Be sure not to read a moved-from value.
* tests/c++.at (C++ Variant-based Symbols Unit Tests): Check this case.
This commit is contained in:
Akim Demaille
2018-12-23 19:37:30 +01:00
parent 45cd7dfb7f
commit 807bf60cfc
3 changed files with 23 additions and 3 deletions

1
THANKS
View File

@@ -180,6 +180,7 @@ Wayne Green wayne@infosavvy.com
Wei Song wsong83@gmail.com Wei Song wsong83@gmail.com
Wojciech Polak polak@gnu.org Wojciech Polak polak@gnu.org
Wolfgang S. Kechel wolfgang.kechel@prs.de Wolfgang S. Kechel wolfgang.kechel@prs.de
Wolfgang Thaller wolfgang.thaller@gmx.net
Wolfram Wagner ww@mpi-sb.mpg.de Wolfram Wagner ww@mpi-sb.mpg.de
Wwp subscript@free.fr Wwp subscript@free.fr
xolodho xolodho@gmail.com xolodho xolodho@gmail.com

View File

@@ -303,8 +303,8 @@ m4_define([b4_symbol_type_declare],
/// Default constructor. /// Default constructor.
by_type (); by_type ();
/// Copy constructor. /// Move or copy constructor.
by_type (const by_type& that); by_type (YY_RVREF (by_type) that);
/// The symbol type as needed by the constructor. /// The symbol type as needed by the constructor.
typedef token_type kind_type; typedef token_type kind_type;
@@ -368,7 +368,7 @@ m4_define([b4_public_types_define],
, value (]b4_variant_if([], [YY_MOVE (that.value)]))b4_locations_if([ , value (]b4_variant_if([], [YY_MOVE (that.value)]))b4_locations_if([
, location (YY_MOVE (that.location))])[ , location (YY_MOVE (that.location))])[
{]b4_variant_if([ {]b4_variant_if([
b4_symbol_variant([that.type_get ()], [value], [YY_MOVE_OR_COPY], b4_symbol_variant([this->type_get ()], [value], [YY_MOVE_OR_COPY],
[YY_MOVE (that.value)]) [YY_MOVE (that.value)])
])[} ])[}
@@ -446,9 +446,17 @@ m4_define([b4_public_types_define],
: type (empty_symbol) : type (empty_symbol)
{} {}
#if 201103L <= YY_CPLUSPLUS
]b4_inline([$1])b4_parser_class_name[::by_type::by_type (by_type&& that)
: type (that.type)
{
that.clear ();
}
#else
]b4_inline([$1])b4_parser_class_name[::by_type::by_type (const by_type& that) ]b4_inline([$1])b4_parser_class_name[::by_type::by_type (const by_type& that)
: type (that.type) : type (that.type)
{} {}
#endif
]b4_inline([$1])b4_parser_class_name[::by_type::by_type (token_type t) ]b4_inline([$1])b4_parser_class_name[::by_type::by_type (token_type t)
: type (yytranslate_ (t)) : type (yytranslate_ (t))

View File

@@ -160,6 +160,17 @@ int main()
assert_eq (s.value.as<int> (), 12); assert_eq (s.value.as<int> (), 12);
} }
// symbol_type: move constructor.
#if 201103L <= YY_CPLUSPLUS
{
auto s = parser::make_INT (42);
auto s2 = std::move (s);
assert_eq (s2.value.as<int> (), 42);
// Used to crash here, because s was improperly cleared, and
// its destructor tried to delete its (moved) value.
}
#endif
// stack_symbol_type: construction, accessor. // stack_symbol_type: construction, accessor.
{ {
#if 201103L <= YY_CPLUSPLUS #if 201103L <= YY_CPLUSPLUS