]> sourceware.org Git - glibc.git/commitdiff
elf: handle addition overflow in _dl_find_object_update_1 [BZ #32245]
authorAurelien Jarno <aurelien@aurel32.net>
Sun, 10 Nov 2024 09:50:34 +0000 (10:50 +0100)
committerAurelien Jarno <aurelien@aurel32.net>
Wed, 13 Nov 2024 22:06:43 +0000 (23:06 +0100)
The remaining_to_add variable can be 0 if (current_used + count) wraps,
This is caught by GCC 14+ on hppa, which determines from there that
target_seg could be be NULL when remaining_to_add is zero, which in
turns causes a -Wstringop-overflow warning:

 In file included from ../include/atomic.h:49,
                  from dl-find_object.c:20:
 In function '_dlfo_update_init_seg',
     inlined from '_dl_find_object_update_1' at dl-find_object.c:689:30,
     inlined from '_dl_find_object_update' at dl-find_object.c:805:13:
 ../sysdeps/unix/sysv/linux/hppa/atomic-machine.h:44:4: error: '__atomic_store_4' writing 4 bytes into a region of size 0 overflows the destination [-Werror=stringop-overflow=]
    44 |    __atomic_store_n ((mem), (val), __ATOMIC_RELAXED);                        \
       |    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 dl-find_object.c:644:3: note: in expansion of macro 'atomic_store_relaxed'
   644 |   atomic_store_relaxed (&seg->size, new_seg_size);
       |   ^~~~~~~~~~~~~~~~~~~~
 In function '_dl_find_object_update':
 cc1: note: destination object is likely at address zero

In practice, this is not possible as it represent counts of link maps.
Link maps have sizes larger than 1 byte, so the sum of any two link map
counts will always fit within a size_t without wrapping around.

This patch therefore adds a check on remaining_to_add == 0 and tell GCC
that this can not happen using __builtin_unreachable.

Thanks to Andreas Schwab for the investigation.

Closes: BZ #32245
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Tested-by: John David Anglin <dave.anglin@bell.net>
Reviewed-by: Florian Weimer <fweimer@redhat.com>
elf/dl-find_object.c

index 449302eda35ce96fec45f6e871baf8ca8b74c12c..ae18b438d321b2c37c3e89574f8f54fd75202361 100644 (file)
@@ -662,6 +662,14 @@ _dl_find_object_update_1 (struct link_map **loaded, size_t count)
     = _dlfo_loaded_mappings[!active_idx];
   size_t remaining_to_add = current_used + count;
 
+  /* remaining_to_add can be 0 if (current_used + count) wraps, but in practice
+     this is not possible as it represent counts of link maps.  Link maps have
+     sizes larger than 1 byte, so the sum of any two link map counts will
+     always fit within a size_t without wrapping around.  This check ensures
+     that target_seg is not erroneously considered potentially NULL by GCC. */
+  if (remaining_to_add == 0)
+    __builtin_unreachable ();
+
   /* Ensure that the new segment chain has enough space.  */
   {
     size_t new_allocated
This page took 0.043332 seconds and 5 git commands to generate.