From: Tulio A M Mendes Date: Thu, 16 Apr 2026 05:36:47 +0000 (-0300) Subject: fix(ulibc): add null-pointer guards in __libc_init_array/fini_array X-Git-Url: https://projects.tadryanom.me/?a=commitdiff_plain;h=5d41d2c53c7dfa60f6fb0289225cfb3cebf53b9b;p=AdrOS.git fix(ulibc): add null-pointer guards in __libc_init_array/fini_array In a PIC shared library build, linker-generated symbols like __init_array_start, __fini_array_end, and _init may remain SHN_UNDEF (value 0) when the library has no .init_array/.fini_array sections. The GOT entries for these resolve to 0. Added null-pointer checks using volatile pointers (to prevent the compiler from assuming the address is always non-null) for all init/fini array pointers and for _init/_fini function pointers. This prevents crashes when these symbols are unresolved. --- diff --git a/user/ulibc/src/init_fini.c b/user/ulibc/src/init_fini.c index d409d043..91aed6a9 100644 --- a/user/ulibc/src/init_fini.c +++ b/user/ulibc/src/init_fini.c @@ -17,42 +17,75 @@ * The symbols __preinit_array_start, __init_array_start, __init_array_end, * __fini_array_start, __fini_array_end are defined by the linker script. * _init() and _fini() come from crti.o/crtn.o (GCC CRT files). + * + * In a shared-library build these linker-generated symbols may remain + * SHN_UNDEF (value 0) when the library has no .init_array / .fini_array + * sections. We guard against that by checking the GOT entries for NULL. */ #include typedef void (*init_func)(void); -extern init_func __preinit_array_start[]; -extern init_func __preinit_array_end[]; -extern init_func __init_array_start[]; -extern init_func __init_array_end[]; -extern init_func __fini_array_start[]; -extern init_func __fini_array_end[]; +/* These are resolved via the GOT in PIC mode; their values come from + * GLOB_DAT relocations. When the linker doesn't define them they + * resolve to 0. We read them through a volatile pointer so the + * compiler cannot assume they are non-null. */ +extern init_func *volatile __preinit_array_start[]; +extern init_func *volatile __preinit_array_end[]; +extern init_func *volatile __init_array_start[]; +extern init_func *volatile __init_array_end[]; +extern init_func *volatile __fini_array_start[]; +extern init_func *volatile __fini_array_end[]; extern void _init(void); extern void _fini(void); +/* Read _init/_fini through volatile to allow null check. + * In PIC shared libs, these resolve via GOT and may be 0. */ +static volatile init_func _init_ptr = _init; +static volatile init_func _fini_ptr = _fini; + void __libc_init_array(void) { size_t count, i; + init_func *s, *e; - count = (size_t)(__preinit_array_end - __preinit_array_start); - for (i = 0; i < count; i++) - __preinit_array_start[i](); + s = (init_func*)__preinit_array_start; + e = (init_func*)__preinit_array_end; + if (s && e) { + count = (size_t)(e - s); + for (i = 0; i < count; i++) + s[i](); + } - _init(); + { + init_func fn = _init_ptr; + if (fn) fn(); + } - count = (size_t)(__init_array_end - __init_array_start); - for (i = 0; i < count; i++) - __init_array_start[i](); + s = (init_func*)__init_array_start; + e = (init_func*)__init_array_end; + if (s && e) { + count = (size_t)(e - s); + for (i = 0; i < count; i++) + s[i](); + } } void __libc_fini_array(void) { size_t count; + init_func *s, *e; - count = (size_t)(__fini_array_end - __fini_array_start); - while (count-- > 0) - __fini_array_start[count](); + s = (init_func*)__fini_array_start; + e = (init_func*)__fini_array_end; + if (s && e) { + count = (size_t)(e - s); + while (count-- > 0) + s[count](); + } - _fini(); + { + init_func fn = _fini_ptr; + if (fn) fn(); + } }