fix potential crash when printing a changing hash table
If a mutable hash table changes while it's being printed, various parts of the printing function could see a mismatch between the current size and an old array size. To avoid this problem, extract the size whenever extracting the array.
This commit is contained in:
parent
4b02c169d7
commit
ba1f5be532
|
@ -268,6 +268,26 @@
|
||||||
(loop (sub1 i))))))
|
(loop (sub1 i))))))
|
||||||
|
|
||||||
;; ----------------------------------------
|
;; ----------------------------------------
|
||||||
|
;; Check that printing a hash table doesn't crash
|
||||||
|
;; if the table changes while it's being printed
|
||||||
|
;; (or checked for cycles):
|
||||||
|
|
||||||
|
(let ()
|
||||||
|
(define ht (make-hash))
|
||||||
|
|
||||||
|
(struct trouble (t)
|
||||||
|
#:property prop:custom-write
|
||||||
|
(lambda (s p mode)
|
||||||
|
(hash-set! ht (random) 'ok)
|
||||||
|
(fprintf p "trouble")))
|
||||||
|
|
||||||
|
(for ([i (in-range 100)])
|
||||||
|
(hash-set! ht (trouble i) i))
|
||||||
|
|
||||||
|
(for ([i 20])
|
||||||
|
(define o (open-output-bytes))
|
||||||
|
(print ht o)))
|
||||||
|
|
||||||
|
;; ----------------------------------------
|
||||||
|
|
||||||
(report-errs)
|
(report-errs)
|
||||||
|
|
|
@ -651,7 +651,7 @@ static int check_cycles(Scheme_Object *obj, int for_write, Scheme_Hash_Table *ht
|
||||||
/* got here => printable */
|
/* got here => printable */
|
||||||
Scheme_Hash_Table *t;
|
Scheme_Hash_Table *t;
|
||||||
Scheme_Object **keys, **vals, *val, *key;
|
Scheme_Object **keys, **vals, *val, *key;
|
||||||
int i;
|
int i, size;
|
||||||
|
|
||||||
if (SCHEME_NP_CHAPERONEP(obj))
|
if (SCHEME_NP_CHAPERONEP(obj))
|
||||||
t = (Scheme_Hash_Table *)SCHEME_CHAPERONE_VAL(obj);
|
t = (Scheme_Hash_Table *)SCHEME_CHAPERONE_VAL(obj);
|
||||||
|
@ -660,8 +660,9 @@ static int check_cycles(Scheme_Object *obj, int for_write, Scheme_Hash_Table *ht
|
||||||
|
|
||||||
keys = t->keys;
|
keys = t->keys;
|
||||||
vals = t->vals;
|
vals = t->vals;
|
||||||
|
size = t->size;
|
||||||
res = 0;
|
res = 0;
|
||||||
for (i = 0; i < t->size; i++) {
|
for (i = 0; i < size; i++) {
|
||||||
if (vals[i]) {
|
if (vals[i]) {
|
||||||
key = keys[i];
|
key = keys[i];
|
||||||
if (!SAME_OBJ((Scheme_Object *)t, obj))
|
if (!SAME_OBJ((Scheme_Object *)t, obj))
|
||||||
|
@ -928,7 +929,7 @@ static void setup_graph_table(Scheme_Object *obj, int for_write, Scheme_Hash_Tab
|
||||||
} else if (pp && SCHEME_CHAPERONE_HASHTPx(obj)) { /* got here => printable */
|
} else if (pp && SCHEME_CHAPERONE_HASHTPx(obj)) { /* got here => printable */
|
||||||
Scheme_Hash_Table *t;
|
Scheme_Hash_Table *t;
|
||||||
Scheme_Object **keys, **vals, *val, *key;
|
Scheme_Object **keys, **vals, *val, *key;
|
||||||
int i;
|
int i, size;
|
||||||
|
|
||||||
if (SCHEME_NP_CHAPERONEP(obj))
|
if (SCHEME_NP_CHAPERONEP(obj))
|
||||||
t = (Scheme_Hash_Table *)SCHEME_CHAPERONE_VAL(obj);
|
t = (Scheme_Hash_Table *)SCHEME_CHAPERONE_VAL(obj);
|
||||||
|
@ -937,7 +938,8 @@ static void setup_graph_table(Scheme_Object *obj, int for_write, Scheme_Hash_Tab
|
||||||
|
|
||||||
keys = t->keys;
|
keys = t->keys;
|
||||||
vals = t->vals;
|
vals = t->vals;
|
||||||
for (i = 0; i < t->size; i++) {
|
size = t->size;
|
||||||
|
for (i = 0; i < size; i++) {
|
||||||
if (vals[i]) {
|
if (vals[i]) {
|
||||||
key = keys[i];
|
key = keys[i];
|
||||||
if (!SAME_OBJ((Scheme_Object *)t, obj))
|
if (!SAME_OBJ((Scheme_Object *)t, obj))
|
||||||
|
@ -2360,7 +2362,7 @@ print(Scheme_Object *obj, int notdisplay, int compact, Scheme_Hash_Table *ht,
|
||||||
Scheme_Hash_Table *t;
|
Scheme_Hash_Table *t;
|
||||||
Scheme_Hash_Tree *tr;
|
Scheme_Hash_Tree *tr;
|
||||||
Scheme_Object **keys, **vals, *val, *key, *orig, **sorted_keys;
|
Scheme_Object **keys, **vals, *val, *key, *orig, **sorted_keys;
|
||||||
intptr_t i, size, count;
|
intptr_t i, size, count, vals_size;
|
||||||
int did_one = 0;
|
int did_one = 0;
|
||||||
mzlonglong pos;
|
mzlonglong pos;
|
||||||
|
|
||||||
|
@ -2417,10 +2419,12 @@ print(Scheme_Object *obj, int notdisplay, int compact, Scheme_Hash_Table *ht,
|
||||||
keys = t->keys;
|
keys = t->keys;
|
||||||
vals = t->vals;
|
vals = t->vals;
|
||||||
size = t->size;
|
size = t->size;
|
||||||
|
vals_size = size;
|
||||||
count = t->count;
|
count = t->count;
|
||||||
} else {
|
} else {
|
||||||
keys = NULL;
|
keys = NULL;
|
||||||
vals = NULL;
|
vals = NULL;
|
||||||
|
vals_size = 0;
|
||||||
size = tr->count;
|
size = tr->count;
|
||||||
count = size;
|
count = size;
|
||||||
}
|
}
|
||||||
|
@ -2451,7 +2455,7 @@ print(Scheme_Object *obj, int notdisplay, int compact, Scheme_Hash_Table *ht,
|
||||||
if (!SAME_OBJ(obj, orig))
|
if (!SAME_OBJ(obj, orig))
|
||||||
val = scheme_chaperone_hash_traversal_get(orig, key, &key);
|
val = scheme_chaperone_hash_traversal_get(orig, key, &key);
|
||||||
} else {
|
} else {
|
||||||
if (i < t->size) {
|
if (i < vals_size) {
|
||||||
val = vals[i];
|
val = vals[i];
|
||||||
key = keys[i];
|
key = keys[i];
|
||||||
if (!SAME_OBJ(obj, orig))
|
if (!SAME_OBJ(obj, orig))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user