diff options
| author | Paul Eggert | 2019-07-20 19:40:03 -0700 |
|---|---|---|
| committer | Paul Eggert | 2019-07-20 20:13:46 -0700 |
| commit | 515afc9c15870cd7bd6b96e2d8b89938116923ac (patch) | |
| tree | e57bf126a8e6076edb1c4fa87e4908c94fd8d779 /src/bytecode.c | |
| parent | b6f194a0fb6dbd1b19aa01f95a955f5b8b23b40e (diff) | |
| download | emacs-515afc9c15870cd7bd6b96e2d8b89938116923ac.tar.gz emacs-515afc9c15870cd7bd6b96e2d8b89938116923ac.zip | |
Fix crash if user test munges hash table
* src/fns.c (restore_mutability)
(hash_table_user_defined_call): New functions.
(cmpfn_user_defined, hashfn_user_defined): Use them.
(make_hash_table, copy_hash_table):
Mark new hash table as mutable.
(check_mutable_hash_table): New function.
(Fclrhash, Fputhash, Fremhash): Use it instead of CHECK_IMPURE.
* src/lisp.h (struct hash_table_test): User-defined functions
now take pointers to struct Lisp_Hash_Table, not to struct
hash_table_test. All uses changed.
(struct Lisp_Hash_Table): New member ‘mutable’.
* src/pdumper.c (dump_hash_table): Copy it.
* test/src/fns-tests.el (test-hash-function-that-mutates-hash-table):
New test, which tests for the bug.
Diffstat (limited to 'src/bytecode.c')
| -rw-r--r-- | src/bytecode.c | 5 |
1 files changed, 2 insertions, 3 deletions
diff --git a/src/bytecode.c b/src/bytecode.c index e82de026a82..d668a9a6a15 100644 --- a/src/bytecode.c +++ b/src/bytecode.c | |||
| @@ -1410,14 +1410,13 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, | |||
| 1410 | { /* Do a linear search if there are not many cases | 1410 | { /* Do a linear search if there are not many cases |
| 1411 | FIXME: 5 is arbitrarily chosen. */ | 1411 | FIXME: 5 is arbitrarily chosen. */ |
| 1412 | Lisp_Object hash_code | 1412 | Lisp_Object hash_code |
| 1413 | = h->test.cmpfn ? h->test.hashfn (v1, &h->test) : Qnil; | 1413 | = h->test.cmpfn ? h->test.hashfn (v1, h) : Qnil; |
| 1414 | 1414 | ||
| 1415 | for (i = h->count; 0 <= --i; ) | 1415 | for (i = h->count; 0 <= --i; ) |
| 1416 | if (EQ (v1, HASH_KEY (h, i)) | 1416 | if (EQ (v1, HASH_KEY (h, i)) |
| 1417 | || (h->test.cmpfn | 1417 | || (h->test.cmpfn |
| 1418 | && EQ (hash_code, HASH_HASH (h, i)) | 1418 | && EQ (hash_code, HASH_HASH (h, i)) |
| 1419 | && !NILP (h->test.cmpfn (v1, HASH_KEY (h, i), | 1419 | && !NILP (h->test.cmpfn (v1, HASH_KEY (h, i), h)))) |
| 1420 | &h->test)))) | ||
| 1421 | break; | 1420 | break; |
| 1422 | } | 1421 | } |
| 1423 | else | 1422 | else |