Browse Source

Add infinite loop check and early out in `map_insert_hash_dynamic`

gingerBill 1 year ago
parent
commit
ac10f504e4
1 changed files with 13 additions and 3 deletions
  1. 13 3
      base/runtime/dynamic_map_internal.odin

+ 13 - 3
base/runtime/dynamic_map_internal.odin

@@ -391,7 +391,8 @@ map_alloc_dynamic :: proc "odin" (info: ^Map_Info, log2_capacity: uintptr, alloc
 // arrays to reduce variance. This swapping can only be done with memcpy since
 // arrays to reduce variance. This swapping can only be done with memcpy since
 // there is no type information.
 // there is no type information.
 //
 //
-// This procedure returns the address of the just inserted value.
+// This procedure returns the address of the just inserted value, and will
+// return 'nil' if there was no room to insert the entry
 @(require_results)
 @(require_results)
 map_insert_hash_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, h: Map_Hash, ik: uintptr, iv: uintptr) -> (result: uintptr) {
 map_insert_hash_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, h: Map_Hash, ik: uintptr, iv: uintptr) -> (result: uintptr) {
 	h        := h
 	h        := h
@@ -415,6 +416,11 @@ map_insert_hash_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^
 	tv := map_cell_index_dynamic(sv, info.vs, 1)
 	tv := map_cell_index_dynamic(sv, info.vs, 1)
 
 
 	swap_loop: for {
 	swap_loop: for {
+		if distance > mask
+			// Failed to find an empty slot and prevent infinite loop
+			return 0
+		}
+
 		element_hash := hs[pos]
 		element_hash := hs[pos]
 
 
 		if map_hash_is_empty(element_hash) {
 		if map_hash_is_empty(element_hash) {
@@ -898,7 +904,9 @@ __dynamic_map_set :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_In
 	}
 	}
 
 
 	result := map_insert_hash_dynamic(m, info, hash, uintptr(key), uintptr(value))
 	result := map_insert_hash_dynamic(m, info, hash, uintptr(key), uintptr(value))
-	m.len += 1
+	if result != 0 {
+		m.len += 1
+	}
 	return rawptr(result)
 	return rawptr(result)
 }
 }
 __dynamic_map_set_extra_without_hash :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, key, value: rawptr, loc := #caller_location) -> (prev_key_ptr, value_ptr: rawptr) {
 __dynamic_map_set_extra_without_hash :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, key, value: rawptr, loc := #caller_location) -> (prev_key_ptr, value_ptr: rawptr) {
@@ -921,7 +929,9 @@ __dynamic_map_set_extra :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^
 	}
 	}
 
 
 	result := map_insert_hash_dynamic(m, info, hash, uintptr(key), uintptr(value))
 	result := map_insert_hash_dynamic(m, info, hash, uintptr(key), uintptr(value))
-	m.len += 1
+	if result != 0 {
+		m.len += 1
+	}
 	return nil, rawptr(result)
 	return nil, rawptr(result)
 }
 }