@@ -800,6 +800,42 @@ static void enqueue_free_slab(struct size_class *c, struct slab_metadata *metada
800800 c -> free_slabs_tail = substitute ;
801801}
802802
803+ static inline void memory_corruption_check_small (const void * p , const char * unaligned_msg , const char * unused_slot_msg ,
804+ const char * quarantine_msg ) {
805+ struct slab_size_class_info size_class_info = slab_size_class (p );
806+ size_t class = size_class_info .class ;
807+ struct size_class * c = & ro .size_class_metadata [size_class_info .arena ][class ];
808+ size_t size = c -> size ;
809+ bool is_zero_size = class == 0 ;
810+ size_t slab_size = c -> slab_size ;
811+
812+ mutex_lock (& c -> lock );
813+
814+ const struct slab_metadata * metadata = get_metadata (c , p );
815+ void * slab = get_slab (c , slab_size , metadata );
816+ size_t slot = libdivide_u32_do ((const char * )p - (const char * )slab , & c -> size_divisor );
817+
818+ if (unlikely (slot_pointer (size , slab , slot ) != p )) {
819+ fatal_error (unaligned_msg );
820+ }
821+
822+ if (unlikely (!is_used_slot (metadata , slot ))) {
823+ fatal_error (unused_slot_msg );
824+ }
825+
826+ if (likely (!is_zero_size )) {
827+ check_canary (metadata , p , size );
828+ }
829+
830+ #if SLAB_QUARANTINE
831+ if (unlikely (is_quarantine_slot (metadata , slot ))) {
832+ fatal_error (quarantine_msg );
833+ }
834+ #endif
835+
836+ mutex_unlock (& c -> lock );
837+ }
838+
803839// preserves errno
804840static inline void deallocate_small (void * p , const size_t * expected_size ) {
805841 struct slab_size_class_info size_class_info = slab_size_class (p );
@@ -1558,10 +1594,13 @@ EXPORT void *h_realloc(void *old, size_t size) {
15581594 bool old_in_slab_region = old < get_slab_region_end () && old >= ro .slab_region_start ;
15591595 if (old_in_slab_region ) {
15601596 old_size = slab_usable_size (old );
1597+ thread_unseal_metadata ();
15611598 if (size <= max_slab_size_class && get_size_info (size ).size == old_size ) {
1599+ memory_corruption_check_small (old , "invalid unaligned h_realloc" ,
1600+ "invalid h_realloc (unused)" , "invalid h_realloc (quarantine)" );
1601+ thread_seal_metadata ();
15621602 return old_orig ;
15631603 }
1564- thread_unseal_metadata ();
15651604 } else {
15661605 enforce_init ();
15671606 thread_unseal_metadata ();
@@ -1755,41 +1794,6 @@ EXPORT void h_free_sized(void *p, size_t expected_size) {
17551794 thread_seal_metadata ();
17561795}
17571796
1758- static inline void memory_corruption_check_small (const void * p ) {
1759- struct slab_size_class_info size_class_info = slab_size_class (p );
1760- size_t class = size_class_info .class ;
1761- struct size_class * c = & ro .size_class_metadata [size_class_info .arena ][class ];
1762- size_t size = c -> size ;
1763- bool is_zero_size = class == 0 ;
1764- size_t slab_size = c -> slab_size ;
1765-
1766- mutex_lock (& c -> lock );
1767-
1768- const struct slab_metadata * metadata = get_metadata (c , p );
1769- void * slab = get_slab (c , slab_size , metadata );
1770- size_t slot = libdivide_u32_do ((const char * )p - (const char * )slab , & c -> size_divisor );
1771-
1772- if (unlikely (slot_pointer (size , slab , slot ) != p )) {
1773- fatal_error ("invalid unaligned malloc_usable_size" );
1774- }
1775-
1776- if (unlikely (!is_used_slot (metadata , slot ))) {
1777- fatal_error ("invalid malloc_usable_size" );
1778- }
1779-
1780- if (likely (!is_zero_size )) {
1781- check_canary (metadata , p , size );
1782- }
1783-
1784- #if SLAB_QUARANTINE
1785- if (unlikely (is_quarantine_slot (metadata , slot ))) {
1786- fatal_error ("invalid malloc_usable_size (quarantine)" );
1787- }
1788- #endif
1789-
1790- mutex_unlock (& c -> lock );
1791- }
1792-
17931797EXPORT size_t h_malloc_usable_size (H_MALLOC_USABLE_SIZE_CONST void * arg ) {
17941798 if (arg == NULL ) {
17951799 return 0 ;
@@ -1799,7 +1803,8 @@ EXPORT size_t h_malloc_usable_size(H_MALLOC_USABLE_SIZE_CONST void *arg) {
17991803
18001804 if (p < get_slab_region_end () && p >= ro .slab_region_start ) {
18011805 thread_unseal_metadata ();
1802- memory_corruption_check_small (p );
1806+ memory_corruption_check_small (p , "invalid unaligned malloc_usable_size" ,
1807+ "invalid malloc_usable_size (unused)" , "invalid malloc_usable_size (quarantine)" );
18031808 thread_seal_metadata ();
18041809
18051810 size_t size = slab_usable_size (p );
0 commit comments