From eeb118d8438919e7f1eb8f80851e6dadaaaab14f Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Sat, 17 Dec 2016 01:01:06 +0300 Subject: [PATCH] Eliminate 'integer shift by a negative amount' code defect in finalize * finalize.c (GC_register_disappearing_link_inner): Add assertion that dl_hashtbl->log_size is non-negative after GC_grow_table() call. * finalize.c (GC_unregister_disappearing_link_inner): If dl_hashtbl->log_size is negative then return immediately (to avoid an integer value shift by log_size==-1 in HASH2). * finalize.c [!GC_MOVE_DISAPPEARING_LINK_NOT_NEEDED] (GC_move_disappearing_link_inner): Likewise. * finalize.c (GC_register_finalizer_inner): Add assertion that log_fo_table_size is non-negative after GC_grow_table() call. * finalize.c (GC_finalize): Add assertion that log_fo_table_size is non-negative unless GC_fnlz_roots.finalize_now is null. --- finalize.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/finalize.c b/finalize.c index c765d628..50caaa55 100644 --- a/finalize.c +++ b/finalize.c @@ -158,6 +158,7 @@ STATIC int GC_register_disappearing_link_inner( || dl_hashtbl -> entries > ((word)1 << dl_hashtbl -> log_size)) { GC_grow_table((struct hash_chain_entry ***)&dl_hashtbl -> head, &dl_hashtbl -> log_size); + GC_ASSERT(dl_hashtbl->log_size >= 0); GC_COND_LOG_PRINTF("Grew %s table to %u entries\n", tbl_log_name, 1 << (unsigned)dl_hashtbl -> log_size); } @@ -229,8 +230,12 @@ GC_INLINE struct disappearing_link *GC_unregister_disappearing_link_inner( { struct disappearing_link *curr_dl; struct disappearing_link *prev_dl = NULL; - size_t index = HASH2(link, dl_hashtbl->log_size); + size_t index; + + if (dl_hashtbl->log_size == -1) + return NULL; /* prevent integer shift by a negative amount */ + index = HASH2(link, dl_hashtbl->log_size); for (curr_dl = dl_hashtbl -> head[index]; curr_dl; curr_dl = dl_next(curr_dl)) { if (curr_dl -> dl_hidden_link == GC_HIDE_POINTER(link)) { @@ -492,6 +497,9 @@ GC_API GC_await_finalize_proc GC_CALL GC_get_await_finalize_proc(void) word curr_hidden_link; word new_hidden_link; + if (dl_hashtbl->log_size == -1) + return GC_NOT_FOUND; /* prevent integer shift by a negative amount */ + /* Find current link. */ curr_index = HASH2(link, dl_hashtbl -> log_size); curr_hidden_link = GC_HIDE_POINTER(link); @@ -642,6 +650,7 @@ STATIC void GC_register_finalizer_inner(void * obj, || GC_fo_entries > ((word)1 << log_fo_table_size)) { GC_grow_table((struct hash_chain_entry ***)&GC_fnlz_roots.fo_head, &log_fo_table_size); + GC_ASSERT(log_fo_table_size >= 0); GC_COND_LOG_PRINTF("Grew fo table to %u entries\n", 1 << (unsigned)log_fo_table_size); } @@ -1036,6 +1045,7 @@ GC_INNER void GC_finalize(void) other finalizable objects */ if (need_unreachable_finalization) { curr_fo = GC_fnlz_roots.finalize_now; + GC_ASSERT(NULL == curr_fo || log_fo_table_size >= 0); prev_fo = NULL; while (curr_fo != NULL) { next_fo = fo_next(curr_fo); -- 2.40.0