Eliminate 'integer shift by a negative amount' code defect in finalize
authorIvan Maidanski <ivmai@mail.ru>
Fri, 16 Dec 2016 22:01:06 +0000 (01:01 +0300)
committerIvan Maidanski <ivmai@mail.ru>
Fri, 16 Dec 2016 22:01:06 +0000 (01:01 +0300)
* 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

index c765d62..50caaa5 100644 (file)
@@ -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);