From 2313f891bd1ceede29af0e318badf7e11240ab0a Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Sun, 6 Dec 2020 16:21:29 +0100 Subject: [PATCH] glr2.cc: add sanity checks in glr_stack_item We obviously have broken pointer arithmetics that hands us glr_stack_items that are not glr_stack_items. Have a simple check for this, to have earlier failures. * data/skeletons/glr2.cc (glr_stack_item::check_): New. Use it. (glr_stack_item::contents): Avoid the useless struct. Fix minor stylistic issues. --- data/skeletons/glr2.cc | 69 ++++++++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 23 deletions(-) diff --git a/data/skeletons/glr2.cc b/data/skeletons/glr2.cc index ea4fa43d..07a162dc 100644 --- a/data/skeletons/glr2.cc +++ b/data/skeletons/glr2.cc @@ -1155,7 +1155,8 @@ class glr_stack_item { public: glr_stack_item (bool state = true) - : is_state_ (state) + : is_state_ (state)]b4_parse_assert_if([[ + , magic_ (MAGIC)]])[ { if (is_state_) new (&raw_) glr_state; @@ -1163,21 +1164,26 @@ public: new (&raw_) semantic_option; } - glr_stack_item(const glr_stack_item& other) YY_NOEXCEPT YY_NOTHROW - : is_state_(other.is_state_) - { - std::memcpy(raw_, other.raw_, union_size); + glr_stack_item (const glr_stack_item& other) YY_NOEXCEPT YY_NOTHROW + : is_state_ (other.is_state_)]b4_parse_assert_if([[ + , magic_ (0xDEAD1ACC)]])[ + {]b4_parse_assert_if([[ + other.check_ ();]])[ + std::memcpy (raw_, other.raw_, union_size); } - glr_stack_item& operator=(glr_stack_item other) - { - std::swap(is_state_, other.is_state_); - std::swap(raw_, other.raw_); + glr_stack_item& operator= (glr_stack_item other) + {]b4_parse_assert_if([[ + check_ (); + other.check_ ();]])[ + std::swap (is_state_, other.is_state_); + std::swap (raw_, other.raw_); return *this; } - ~glr_stack_item() - { + ~glr_stack_item () + {]b4_parse_assert_if([[ + check_ ();]])[ if (is_state()) getState().~glr_state(); else @@ -1185,44 +1191,48 @@ public: } glr_state& getState () - { + {]b4_parse_assert_if([[ + check_ ();]])[ YYDASSERT (is_state ()); void *yyp = raw_; return *static_cast (yyp); } const glr_state& getState () const - { - YYDASSERT (is_state()); + {]b4_parse_assert_if([[ + check_ ();]])[ + YYDASSERT (is_state ()); const void *yyp = raw_; return *static_cast (yyp); } semantic_option& getOption () - { + {]b4_parse_assert_if([[ + check_ ();]])[ YYDASSERT (!is_state ()); void *yyp = raw_; return *static_cast (yyp); } const semantic_option& getOption () const - { + {]b4_parse_assert_if([[ + check_ ();]])[ YYDASSERT (!is_state ()); const void *yyp = raw_; return *static_cast (yyp); } bool is_state () const - { + {]b4_parse_assert_if([[ + check_ ();]])[ return is_state_; } private: /// The possible contents of raw_. Since they have constructors, they cannot /// be directly included in the union. - struct contents { - union { - char yystate[sizeof(glr_state)]; - char yyoption[sizeof(semantic_option)]; - }; + union contents + { + char yystate[sizeof (glr_state)]; + char yyoption[sizeof (semantic_option)]; }; - enum { union_size = sizeof(contents) }; + enum { union_size = sizeof (contents) }; union { /// Strongest alignment constraints. long double yyalign_me; @@ -1231,6 +1241,17 @@ public: }; /** Type tag for the union. */ bool is_state_; + +]b4_parse_assert_if([[ + // Check invariants. + void check_ () const + { + YYASSERT (this->magic_ == MAGIC); + YYASSERT (this->is_state_ == false || this->is_state_ == true); + } + // A magic number to check our pointer arithmetics is sane. + enum { MAGIC = 0xDEAD1ACC }; + const unsigned int magic_;]])[ }; glr_state* glr_state::pred () @@ -1272,7 +1293,9 @@ std::ptrdiff_t semantic_option::indexIn(glr_stack_item* array) { } glr_state* semantic_option::state() { + YY_IGNORE_NULL_DEREFERENCE_BEGIN return yystate ? &(asItem(this) - yystate)->getState() : YY_NULLPTR; + YY_IGNORE_NULL_DEREFERENCE_END } const glr_state* semantic_option::state() const {