[PATCH 1/9] glr2.cc: add sanity checks in glr_stack_item

Akim Demaille <[email protected]>
Newsgroups gmane.comp.parsers.bison.patches
Message-ID <[email protected]>
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<glr_state*> (yyp);
   }
   const glr_state& getState () const
-  {
-    YYDASSERT (is_state());
+  {]b4_parse_assert_if([[
+    check_ ();]])[
+    YYDASSERT (is_state ());
     const void *yyp = raw_;
     return *static_cast<const glr_state*> (yyp);
   }
 
   semantic_option& getOption ()
-  {
+  {]b4_parse_assert_if([[
+    check_ ();]])[
     YYDASSERT (!is_state ());
     void *yyp = raw_;
     return *static_cast<semantic_option*> (yyp);
   }
   const semantic_option& getOption () const
-  {
+  {]b4_parse_assert_if([[
+    check_ ();]])[
     YYDASSERT (!is_state ());
     const void *yyp = raw_;
     return *static_cast<const semantic_option*> (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 {
-- 
2.29.2
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.