From 636c9a8042787d0c790d676595f3d56e672ce9f5 Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Fri, 25 Dec 2020 08:53:31 +0100 Subject: [PATCH] glr2.cc: beware of self-assignment In yycompressStack: while (yyr != YY_NULLPTR) { nextFreeItem->check_ (); yyr->check_(); nextFreeItem->setState(*yyr); glr_state& nextFreeState = nextFreeItem->getState(); yyr = yyr->pred(); nextFreeState.setPred(&(nextFreeItem - 1)->getState()); setFirstTop(&nextFreeState); ++nextFreeItem; } it is possible that nextFreeItem and yyr are actually the same state. In which case `nextFreeItem->setState(*yyr)` does really bad things. * data/skeletons/glr2.cc (glr_stack_item::setState): Beware of self-assignment. --- data/skeletons/glr2.cc | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/data/skeletons/glr2.cc b/data/skeletons/glr2.cc index 5af9f6ae..e76a376a 100644 --- a/data/skeletons/glr2.cc +++ b/data/skeletons/glr2.cc @@ -896,6 +896,12 @@ public: return asItem(this); } + const glr_stack_item* asItem () const + {]b4_parse_assert_if([[ + check_ ();]])[ + return asItem (this); + } + private: template static const glr_stack_item* asItem (const T* state) @@ -1272,12 +1278,15 @@ public: {]b4_parse_assert_if([[ check_ (); state.check_ ();]])[ - // FIXME: What about the previous content? Shouldn't it be freed? - // It might be useful to have an explicit "void" state when this item - // is in unused state (in the list of free items), when parse.assert - // is set. - is_state_ = true; - new (&raw_) glr_state (state); + if (this != state.asItem ()) + { + is_state_ = true; + // FIXME: What about the previous content? Shouldn't it be + // freed? It might be useful to have an explicit "void" state + // when this item is in unused state (in the list of free + // items), when parse.assert is set. + new (&raw_) glr_state (state); + } } glr_state& getState ()