groff-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[groff] 03/03: Fix SEGV arising from recursing destructor.


From: G. Branden Robinson
Subject: [groff] 03/03: Fix SEGV arising from recursing destructor.
Date: Tue, 29 Sep 2020 04:40:02 -0400 (EDT)

gbranden pushed a commit to branch master
in repository groff.

commit c788cf8c6bbe939fa11f7ec032e525a7e33f41b6
Author: G. Branden Robinson <g.branden.robinson@gmail.com>
AuthorDate: Tue Sep 29 07:02:25 2020 +1000

    Fix SEGV arising from recursing destructor.
    
    * src/roff/troff/node.h (output_file): Add class member `is_dying` to
      track whether destructor has already been entered; initialize false.
    
    * src/roff/troff/node.cpp (real_output_file::~real_output_file): Set
      `is_dying` true when destructor entered.
    
    * src/roff/troff/div.cpp (cleanup_and_exit): Only delete
      `the_output` object if it is not already being destroyed.
    
    Thanks to "hackerb9" for reporting the problem.  Problem appears to date
    back to groff 1.02 (June 1991) or earlier.
    
    Fixes <https://savannah.gnu.org/bugs/index.php?59202>.
---
 ChangeLog               | 14 ++++++++++++++
 src/roff/troff/div.cpp  |  5 ++++-
 src/roff/troff/node.cpp |  2 ++
 src/roff/troff/node.h   |  1 +
 4 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/ChangeLog b/ChangeLog
index ec58216..f27a875 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,8 +1,22 @@
 2020-09-29  G. Branden Robinson <g.branden.robinson@gmail.com>
 
+       Fix SEGV arising from recursing destructor.
+
+       * src/roff/troff/node.h (output_file): Add class member
+       `is_dying` to track whether destructor has already been entered;
+       initialize false.
+       * src/roff/troff/node.cpp (real_output_file::~real_output_file):
+       Set `is_dying` true when destructor entered.
+       * src/roff/troff/div.cpp (cleanup_and_exit): Only delete
+       `the_output` object if it is not already being destroyed.
        * src/roff/groff/tests/regression_savannah_59202.sh: Add test.
        * src/roff/groff/groff.am (groff_TESTS): Run test.
 
+       Thanks to "hackerb9" for reporting the problem.  Problem appears
+       to date back to groff 1.02 (June 1991) or earlier.
+
+       Fixes <https://savannah.gnu.org/bugs/index.php?59202>.
+
 2020-09-28  G. Branden Robinson <g.branden.robinson@gmail.com>
 
        * tmac/an-old.tmac (register setup): Condition decisions on
diff --git a/src/roff/troff/div.cpp b/src/roff/troff/div.cpp
index 920a38c..2bb0dc4 100644
--- a/src/roff/troff/div.cpp
+++ b/src/roff/troff/div.cpp
@@ -559,7 +559,10 @@ void cleanup_and_exit(int exit_code)
 {
   if (the_output) {
     the_output->trailer(topdiv->get_page_length());
-    delete the_output;
+    // If we're already dying, don't call the_output's destructor.  See
+    // node.cpp:real_output_file::~real_output_file().
+    if (!the_output->is_dying)
+      delete the_output;
   }
   FLUSH_INPUT_PIPE(STDIN_FILENO);
   exit(exit_code);
diff --git a/src/roff/troff/node.cpp b/src/roff/troff/node.cpp
index d696865..37260bd 100644
--- a/src/roff/troff/node.cpp
+++ b/src/roff/troff/node.cpp
@@ -1656,6 +1656,8 @@ real_output_file::~real_output_file()
 {
   if (!fp)
     return;
+  // Prevent destructor from recursing; see div.cpp:cleanup_and_exit().
+  is_dying = true;
   // To avoid looping, set fp to 0 before calling fatal().
   if (ferror(fp) || fflush(fp) < 0) {
     fp = 0;
diff --git a/src/roff/troff/node.h b/src/roff/troff/node.h
index 15b654d..e1c1960 100644
--- a/src/roff/troff/node.h
+++ b/src/roff/troff/node.h
@@ -626,6 +626,7 @@ class output_file {
   char make_g_plus_plus_shut_up;
 public:
   output_file();
+  bool is_dying = false;
   virtual ~output_file();
   virtual void trailer(vunits);
   virtual void flush() = 0;



reply via email to

[Prev in Thread] Current Thread [Next in Thread]