emacs-diffs
[Top][All Lists]
Advanced

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

master 3480071: Fix C-h C-h bug due to mutating a hash key


From: Paul Eggert
Subject: master 3480071: Fix C-h C-h bug due to mutating a hash key
Date: Sat, 15 Feb 2020 18:18:33 -0500 (EST)

branch: master
commit 3480071dfab30eaca7f1d014600b864d2ea22f62
Author: Paul Eggert <address@hidden>
Commit: Paul Eggert <address@hidden>

    Fix C-h C-h bug due to mutating a hash key
    
    Problem reported by Federico Tedin (Bug#39529).
    The problem was that dumping uses a hash table based on 'equal'
    when purecopying compiled objects, but then modifies the compiled
    objects while they are keys in the table.  This no-no was uncovered
    by the sxhash fixes in 2020-01-07T19:23:11Z!address@hidden.
    Eli Zaretski pinpointed the patch that triggered the bug.
    * src/lread.c (read1): When reading a compiled object, replace
    its docstring with a unique negative integer instead of with 0,
    so that purecopy doesn’t unify it with some other compiled object
    that happens to have the same Lisp code.
---
 src/lread.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/src/lread.c b/src/lread.c
index c124d5a..f39e81a 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -2974,6 +2974,21 @@ read1 (Lisp_Object readcharfun, int *pch, bool 
first_in_list)
          vec = XVECTOR (tmp);
          if (vec->header.size == 0)
            invalid_syntax ("Empty byte-code object");
+
+         if (COMPILED_DOC_STRING < vec->header.size
+             && AREF (tmp, COMPILED_DOC_STRING) == make_fixnum (0))
+           {
+             /* read_list found a docstring like '(#$ . 5521)' and treated it
+                as 0.  This placeholder 0 would lead to accidental sharing in
+                purecopy's hash-consing, so replace it with a (hopefully)
+                unique integer placeholder, which is negative so that it is
+                not confused with a DOC file offset.  Eventually
+                Snarf-documentation should replace the placeholder with the
+                actual docstring.  */
+             EMACS_UINT hash = XHASH (tmp) | (INTMASK - INTMASK / 2);
+             ASET (tmp, COMPILED_DOC_STRING, make_ufixnum (hash));
+           }
+
          make_byte_code (vec);
          return tmp;
        }



reply via email to

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