ContextObj::destroy(): Guard against invalid use. (#6082)
authorAina Niemetz <aina.niemetz@gmail.com>
Tue, 9 Mar 2021 20:59:13 +0000 (12:59 -0800)
committerGitHub <noreply@github.com>
Tue, 9 Mar 2021 20:59:13 +0000 (20:59 +0000)
We do not allow that a context object is invalid on destruction.
This guards against invalid use as described in #2607. Note that #2607
proposed to skip invalid objects on destruction. We now rather do not
allow for such a case to occur at all.

src/context/context.cpp

index eaadb9f98ddad1e61c356692343dbfe0727a126d..06485c0ba4fd5fc10da728c129b8c3cebe2d8402 100644 (file)
@@ -209,6 +209,7 @@ ContextObj* ContextObj::restoreAndContinue()
 
     Debug("context") << "NULL restore object! " << this << std::endl;
     pContextObjNext = d_pContextObjNext;
+    d_pScope = nullptr;
 
     // Nothing else to do
   } else {
@@ -237,21 +238,30 @@ ContextObj* ContextObj::restoreAndContinue()
 
 void ContextObj::destroy()
 {
+  /* The object to destroy must be valid, i.e., its current state must belong
+   * to a scope. We remove the object and its previous versions from their
+   * respective scopes below. If this assertion is failing, you may have
+   * created an object at a non-zero level and let it outlive the destruction
+   * of that level. */
+  Assert(d_pScope != nullptr);
   /* Context can be big and complicated, so we only want to process this output
    * if we're really going to use it. (Same goes below.) */
   Debug("context") << "before destroy " << this << " (level " << getLevel()
                    << "):" << std::endl << *getContext() << std::endl;
 
-  for(;;) {
+  for (;;)
+  {
     // If valgrind reports invalid writes on the next few lines,
     // here's a hint: make sure all classes derived from ContextObj in
     // the system properly call destroy() in their destructors.
     // That's needed to maintain this linked list properly.
-    if(next() != NULL) {
+    if (next() != nullptr)
+    {
       next()->prev() = prev();
     }
     *prev() = next();
-    if(d_pContextObjRestore == NULL) {
+    if (d_pContextObjRestore == nullptr)
+    {
       break;
     }
     Debug("context") << "in destroy " << this << ", restore object is "