diff options
| author | Paul Eggert | 2020-02-15 15:12:34 -0800 |
|---|---|---|
| committer | Paul Eggert | 2020-02-15 15:18:28 -0800 |
| commit | 3480071dfab30eaca7f1d014600b864d2ea22f62 (patch) | |
| tree | 9cf1ad2975d575710c2bb5c84a6a28681b3e398a | |
| parent | ccb15ada750ed1a2ed67bc58458022b9d96a9d44 (diff) | |
| download | emacs-3480071dfab30eaca7f1d014600b864d2ea22f62.tar.gz emacs-3480071dfab30eaca7f1d014600b864d2ea22f62.zip | |
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!eggert@cs.ucla.edu.
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.
| -rw-r--r-- | src/lread.c | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/src/lread.c b/src/lread.c index c124d5a1d8f..f39e81ae2cf 100644 --- a/src/lread.c +++ b/src/lread.c | |||
| @@ -2974,6 +2974,21 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list) | |||
| 2974 | vec = XVECTOR (tmp); | 2974 | vec = XVECTOR (tmp); |
| 2975 | if (vec->header.size == 0) | 2975 | if (vec->header.size == 0) |
| 2976 | invalid_syntax ("Empty byte-code object"); | 2976 | invalid_syntax ("Empty byte-code object"); |
| 2977 | |||
| 2978 | if (COMPILED_DOC_STRING < vec->header.size | ||
| 2979 | && AREF (tmp, COMPILED_DOC_STRING) == make_fixnum (0)) | ||
| 2980 | { | ||
| 2981 | /* read_list found a docstring like '(#$ . 5521)' and treated it | ||
| 2982 | as 0. This placeholder 0 would lead to accidental sharing in | ||
| 2983 | purecopy's hash-consing, so replace it with a (hopefully) | ||
| 2984 | unique integer placeholder, which is negative so that it is | ||
| 2985 | not confused with a DOC file offset. Eventually | ||
| 2986 | Snarf-documentation should replace the placeholder with the | ||
| 2987 | actual docstring. */ | ||
| 2988 | EMACS_UINT hash = XHASH (tmp) | (INTMASK - INTMASK / 2); | ||
| 2989 | ASET (tmp, COMPILED_DOC_STRING, make_ufixnum (hash)); | ||
| 2990 | } | ||
| 2991 | |||
| 2977 | make_byte_code (vec); | 2992 | make_byte_code (vec); |
| 2978 | return tmp; | 2993 | return tmp; |
| 2979 | } | 2994 | } |