diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2017-10-23 06:35:35 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2017-10-23 06:35:35 -0700 |
commit | 09ababf4284febbc9c96a62e6711826d110e3eb1 (patch) | |
tree | 06c07a6fcda4d4e29048fb688c83100ccc903c1f | |
parent | 6fb9b42ea256a50d00d4e3c3e37cb7866c4baf29 (diff) | |
download | txr-09ababf4284febbc9c96a62e6711826d110e3eb1.tar.gz txr-09ababf4284febbc9c96a62e6711826d110e3eb1.tar.bz2 txr-09ababf4284febbc9c96a62e6711826d110e3eb1.zip |
hash: fix broken copy_hash.
Impact assessment: this bug affects the correctness of
all programs which rely on copying hash tables. Direct
reliance means the use of copy-hash, or using the generic copy
function on hash objects. Indirect reliance occurs through
hash-diff which uses copy-hash. Nothing in TXR itself calls
hash-diff. The the listener's Tab completion relies on
copy-hash for package-sensitive symbol visibility calculation.
Since that is an interactive feature, the impact is low.
* hash.c (copy_hash_chain): New static function.
(copy_hash): Use copy_hash_chain instead of copy_alist,
since the pairs are hash conses and not regular conses:
they have a hash value field that must be copied.
-rw-r--r-- | hash.c | 16 |
1 files changed, 15 insertions, 1 deletions
@@ -677,6 +677,20 @@ val make_similar_hash(val existing) return hash; } +static val copy_hash_chain(val chain) +{ + list_collect_decl(out, ptail); + + for (; chain; chain = cdr(chain)) { + val entry = car(chain); + val nentry = cons(car(entry), cdr(entry)); + nentry->ch.hash = entry->ch.hash; + ptail = list_collect(ptail, nentry); + } + + return out; +} + val copy_hash(val existing) { struct hash *ex = coerce(struct hash *, cobj_handle(existing, hash_s)); @@ -698,7 +712,7 @@ val copy_hash(val existing) h->acons_new_c_fun = ex->acons_new_c_fun; for (iter = zero; lt(iter, mod); iter = plus(iter, one)) - set(vecref_l(h->table, iter), copy_alist(vecref(ex->table, iter))); + set(vecref_l(h->table, iter), copy_hash_chain(vecref(ex->table, iter))); return hash; } |