aboutsummaryrefslogtreecommitdiffstats
path: root/src/bytecode.c
diff options
context:
space:
mode:
authorPaul Eggert2019-07-20 19:40:03 -0700
committerPaul Eggert2019-07-20 20:13:46 -0700
commit515afc9c15870cd7bd6b96e2d8b89938116923ac (patch)
treee57bf126a8e6076edb1c4fa87e4908c94fd8d779 /src/bytecode.c
parentb6f194a0fb6dbd1b19aa01f95a955f5b8b23b40e (diff)
downloademacs-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.c5
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