From 07a187c5ee5a655a7c993766456c0e4596be66dc Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Sun, 23 Dec 2018 19:37:30 +0100 Subject: [PATCH] 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. --- data/c++.m4 | 14 +++++++++++--- tests/c++.at | 11 +++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/data/c++.m4 b/data/c++.m4 index fed06f6b..47e85930 100644 --- a/data/c++.m4 +++ b/data/c++.m4 @@ -290,8 +290,8 @@ m4_define([b4_symbol_type_declare], /// Default constructor. by_type (); - /// Copy constructor. - by_type (const by_type& that); + /// Move or copy constructor. + by_type (YY_RVREF (by_type) that); /// The symbol type as needed by the constructor. typedef token_type kind_type; @@ -345,7 +345,7 @@ m4_define([b4_public_types_define], , value (]b4_variant_if([], [YY_MOVE (that.value)]))b4_locations_if([ , location (YY_MOVE (that.location))])[ {]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)])])[ } @@ -423,9 +423,17 @@ m4_define([b4_public_types_define], : 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) : type (that.type) {} +#endif ]b4_inline([$1])b4_parser_class_name[::by_type::by_type (token_type t) : type (yytranslate_ (t)) diff --git a/tests/c++.at b/tests/c++.at index 32d837d0..ed15ead1 100644 --- a/tests/c++.at +++ b/tests/c++.at @@ -160,6 +160,17 @@ int main() assert_eq (s.value.as (), 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 (), 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. { #if 201103L <= YY_CPLUSPLUS