fix -fanalyzer warnings (from Arm GCC 14.2/15 at least) (#3013)

* fix -fanalyzer warnings (from Arm GCC 14.2/15 at least) - don't plan to fix false positives from earlier versions

* suppress false positive fanalyzer warning that only shows up in release mode
diff --git a/src/common/pico_base_headers/include/pico/assert.h b/src/common/pico_base_headers/include/pico/assert.h
index a9af542..8b84f44 100644
--- a/src/common/pico_base_headers/include/pico/assert.h
+++ b/src/common/pico_base_headers/include/pico/assert.h
@@ -37,7 +37,7 @@
 #define invalid_params_if_and_return(x, test, rc) ({if (PARAM_ASSERTIONS_ENABLED(x)) assert(!(test)); if (test) return rc; })
 
 #ifdef NDEBUG
-extern void hard_assertion_failure(void);
+extern void __attribute__((noreturn)) hard_assertion_failure(void);
 
 /*! \brief  Perform a runtime assertion always (i.e. not just when NDEBUG is undefined)
 *  \ingroup pico_base
diff --git a/src/rp2_common/hardware_psram/psram.c b/src/rp2_common/hardware_psram/psram.c
index 0010a67..cad27f5 100644
--- a/src/rp2_common/hardware_psram/psram.c
+++ b/src/rp2_common/hardware_psram/psram.c
@@ -389,7 +389,7 @@
     static_assert(FLASH_DEVINFO_SIZE_MAX == FLASH_DEVINFO_SIZE_16M, "expected max region size of 16M");
     extern uint32_t __psram_start__;
     extern uint32_t __psram_end__;
-    uint32_t psram_words = (uint32_t)(&__psram_end__ - &__psram_start__);
+    uint32_t psram_words = ((uintptr_t)&__psram_end__ - (uintptr_t)&__psram_start__) / sizeof(uint32_t);
     if (psram_words > psram_word_size) {
         // Setup to bus fault for variables that don't fit in available PSRAM
         int clear_regions = 0; // Clear no regions by default
diff --git a/src/rp2_common/pico_rand/rand.c b/src/rp2_common/pico_rand/rand.c
index dd539c0..95aedec 100644
--- a/src/rp2_common/pico_rand/rand.c
+++ b/src/rp2_common/pico_rand/rand.c
@@ -224,7 +224,8 @@
                 bit_done = true;
                 if (i == n - 1) {
                     // samples has our random bits, so let's mix them in now
-                    samples = rosc_samples = (rosc_samples << n) | samples;
+                    if (n < 64) samples |= rosc_samples << n;
+                    rosc_samples = samples;
                 }
             }
             spin_unlock(lock, save);
diff --git a/src/rp2_common/pico_runtime_init/runtime_init.c b/src/rp2_common/pico_runtime_init/runtime_init.c
index 5e1ad04..ca55065 100644
--- a/src/rp2_common/pico_runtime_init/runtime_init.c
+++ b/src/rp2_common/pico_runtime_init/runtime_init.c
@@ -216,7 +216,7 @@
 #if !(PICO_NO_RAM_VECTOR_TABLE || PICO_NO_FLASH)
     extern uint32_t __vectors;
     extern uint32_t __vectors_end;
-    uint32_t stored_words = (uint32_t)(&__vectors_end - &__vectors);
+    uint32_t stored_words = ((uintptr_t)&__vectors_end - (uintptr_t)&__vectors) / sizeof(uint32_t);
     __builtin_memcpy(ram_vector_table, &__vectors, 4 * MIN(stored_words, PICO_RAM_VECTOR_TABLE_SIZE));
     for(uint i = stored_words; i<count_of(ram_vector_table); i++) {
         ram_vector_table[i] = (uintptr_t)__unhandled_user_irq;
diff --git a/src/rp2_common/pico_sha256/sha256.c b/src/rp2_common/pico_sha256/sha256.c
index 91009c8..4a69d22 100644
--- a/src/rp2_common/pico_sha256/sha256.c
+++ b/src/rp2_common/pico_sha256/sha256.c
@@ -96,7 +96,11 @@
             while (data_size_bytes >= 4) {
                 // write a whole word
                 sha256_wait_ready_blocking();
+                // false positive; data_size_bytes does indeed prevent us reading off the end
+GCC_Pragma("GCC diagnostic push")
+GCC_Pragma("GCC diagnostic ignored \"-Wanalyzer-out-of-bounds\"")
                 sha256_put_word(*data32++);
+GCC_Pragma("GCC diagnostic pop")
                 data_size_bytes -= 4;
             }
             data = (const uint8_t *)data32;
diff --git a/src/rp2_common/pico_thread_local/thread_local.c b/src/rp2_common/pico_thread_local/thread_local.c
index 7032730..4974786 100644
--- a/src/rp2_common/pico_thread_local/thread_local.c
+++ b/src/rp2_common/pico_thread_local/thread_local.c
@@ -85,6 +85,8 @@
 static inline void _tls_init_from_emutls_or_tdata(void *tls) {
 #if PICO_THREAD_LOCAL_SUPPORT_EMUTLS
     uint8_t *tls_adjusted = ((uint8_t *)tls) - TLS_ADJUST;
+GCC_Pragma("GCC diagnostic push")
+GCC_Pragma("GCC diagnostic ignored \"-Wanalyzer-out-of-bounds\"")
     for (tls_object_t* tls_obj = &__emutls_array_start; tls_obj < &__emutls_array_end; ++tls_obj) {
         if (tls_obj->tplate) {
             memcpy(tls_adjusted + tls_obj->offset, tls_obj->tplate, tls_obj->size);
@@ -92,6 +94,7 @@
             memset(tls_adjusted + tls_obj->offset, 0, tls_obj->size);
         }
     }
+GCC_Pragma("GCC diagnostic pop")
 #endif
 #if PICO_THREAD_LOCAL_SUPPORT_THREAD_POINTER
     // when using thread pointers we expect data to come from tdata/tbss
@@ -239,15 +242,18 @@
         // aligned_alloc is not available in all libraries we support, and it isn't thread safe anyway,
         // so we'll just do the padded malloc
         // tls = aligned_alloc(size, _emutls_align);
-        void *tls = malloc(size + _emutls_align - 1);
-        // note we never free the memory, so bumping the pointer is fine
-        tls = (void *)((((uintptr_t)tls) + (_emutls_align - 1)) & ~(_emutls_align - 1));
-        if (tls) {
+        void *raw = malloc(size + _emutls_align - 1);
+        if (raw) {
+            // note we never free the memory, so bumping the pointer is fine
+            void *tls = (void *)((((uintptr_t)raw) + (_emutls_align - 1)) & ~(_emutls_align - 1));
             _init_tls(tls);
             _set_tls(tls);
         }
     }
+GCC_Pragma("GCC diagnostic push")
+GCC_Pragma("GCC diagnostic ignored \"-Wanalyzer-malloc-leak\"")
     return _get_tls_adjusted_for_core(core_num);
+GCC_Pragma("GCC diagnostic pop")
 }
 
 void* __emutls_get_address(void* obj) {
diff --git a/test/kitchen_sink/kitchen_sink.c b/test/kitchen_sink/kitchen_sink.c
index 0d8e705..398c84a 100644
--- a/test/kitchen_sink/kitchen_sink.c
+++ b/test/kitchen_sink/kitchen_sink.c
@@ -194,13 +194,13 @@
 
     extern uint32_t __load_start_overlay_second;
     extern uint32_t __load_stop_overlay_second;
-    stored_words = (uint32_t)(&__load_stop_overlay_second - &__load_start_overlay_second);
+    stored_words = ((uintptr_t)&__load_stop_overlay_second - (uintptr_t)&__load_start_overlay_second) / sizeof(uint32_t);
     memcpy(&__overlays_start__, &__load_start_overlay_second, 4 * stored_words);
     printf("overlay_second after load = %d, %d\n", overlay_second_one, overlay_second_two);
 
     extern uint32_t __load_start_overlay_first;
     extern uint32_t __load_stop_overlay_first;
-    stored_words = (uint32_t)(&__load_stop_overlay_first - &__load_start_overlay_first);
+    stored_words = ((uintptr_t)&__load_stop_overlay_first - (uintptr_t)&__load_start_overlay_first) / sizeof(uint32_t);
     memcpy(&__overlays_start__, &__load_start_overlay_first, 4 * stored_words);
     printf("overlay_first after load = %d\n", overlay_first);
     printf("overlay_second after overlay_first load = %d, %d\n", overlay_second_one, overlay_second_two);
@@ -211,7 +211,7 @@
     extern uint32_t __extra_data_source__;
     extern uint32_t __extra_data_start__;
     extern uint32_t __extra_data_end__;
-    uint32_t stored_words = (uint32_t)(&__extra_data_end__ - &__extra_data_start__);
+    uint32_t stored_words = ((uintptr_t)&__extra_data_end__ - (uintptr_t)&__extra_data_start__) / sizeof(uint32_t);
     memcpy(&__extra_data_start__, &__extra_data_source__, 4 * stored_words);
 
     printf("extra_data after load = %d\n", extra_data);
diff --git a/test/kitchen_sink/kitchen_sink_cpp.cpp b/test/kitchen_sink/kitchen_sink_cpp.cpp
index 650d36a..8ec96c4 100644
--- a/test/kitchen_sink/kitchen_sink_cpp.cpp
+++ b/test/kitchen_sink/kitchen_sink_cpp.cpp
@@ -16,8 +16,13 @@
     for (const auto &x : sv) {
         puts(x);
     }
+    // false positive
+GCC_Pragma("GCC diagnostic push")
+GCC_Pragma("GCC diagnostic ignored \"-Wanalyzer-possible-null-dereference\"")
     for (const auto &x : vec) {
         printf("Number %d\n", x);
     }
+GCC_Pragma("GCC diagnostic pop")
 }
+
 #endif
diff --git a/test/panic_function_test/panic_function_test.c b/test/panic_function_test/panic_function_test.c
index 7e44575..5b6a9e7 100644
--- a/test/panic_function_test/panic_function_test.c
+++ b/test/panic_function_test/panic_function_test.c
@@ -32,41 +32,42 @@
     int magic2 = va_arg(args, int);
     if (magic2 != MAGIC2) {
         printf("magic2 (%08x) != 0x%08x\n", magic2, MAGIC2);
-        return;
+        goto done;
     }
     double magic3 = va_arg(args, double);
     if (magic3 != MAGIC3) {
         printf("magic3 (%f) != 0x%f\n", magic3, MAGIC3);
-        return;
+        goto done;
     }
 #if PICO_PANIC_FUNCTION_WITH_ALL_VAARGS
     printf("checking remaining vaargs...\n");
     int magic4 = va_arg(args, int);
     if (magic4 != MAGIC4) {
         printf("magic4 (%08x) != 0x%08x\n", magic4, MAGIC4);
-        return;
+        goto done;
     }
     int magic5 = va_arg(args, int);
     if (magic5 != MAGIC5) {
         printf("magic5 (%08x) != 0x%08x\n", magic5, MAGIC5);
-        return;
+        goto done;
     }
     int magic6 = va_arg(args, int);
     if (magic6 != MAGIC6) {
         printf("magic6 (%08x) != 0x%08x\n", magic6, MAGIC6);
-        return;
+        goto done;
     }
     int magic7 = va_arg(args, int);
     if (magic7 != MAGIC7) {
         printf("magic7 (%08x) != 0x%08x\n", magic7, MAGIC7);
-        return;
+        goto done;
     }
 #endif
-    va_end(args);
     puts("PASSED");
 #if PICO_PANIC_FUNCTION_DOES_NOT_RETURN
     __breakpoint();
 #endif
+    done:
+    va_end(args);
 }
 
 int main() {
diff --git a/test/pico_divider_test/CMakeLists.txt b/test/pico_divider_test/CMakeLists.txt
index 095d498..f958e87 100644
--- a/test/pico_divider_test/CMakeLists.txt
+++ b/test/pico_divider_test/CMakeLists.txt
@@ -16,6 +16,8 @@
         pico_set_divider_implementation(pico_divider_test hardware_explicit) # want to compare against compiler impl
     endif()
 
+    target_compile_options(pico_divider_test PRIVATE -Wno-analyzer-use-of-uninitialized-value)
+
     pico_add_extra_outputs(pico_divider_test)
 
     target_compile_definitions(pico_divider_test PRIVATE
diff --git a/test/pico_divider_test/pico_divider_test.c b/test/pico_divider_test/pico_divider_test.c
index 77e1682..7c574fd 100644
--- a/test/pico_divider_test/pico_divider_test.c
+++ b/test/pico_divider_test/pico_divider_test.c
@@ -265,7 +265,6 @@
     return div_u64u64(a, b);
 }
 
-
 void perf_test() {
     *(volatile unsigned int *)0xe000e010=5; // enable SYSTICK at core clock
 
diff --git a/test/pico_float_test/CMakeLists.txt b/test/pico_float_test/CMakeLists.txt
index 660d0c3..ac7b5a5 100644
--- a/test/pico_float_test/CMakeLists.txt
+++ b/test/pico_float_test/CMakeLists.txt
@@ -63,6 +63,9 @@
     target_link_libraries(custom_float_funcs_test_${FLOAT_TYPE} PRIVATE pico_stdlib)
     pico_add_extra_outputs(custom_float_funcs_test_${FLOAT_TYPE})
     pico_set_printf_implementation(custom_float_funcs_test_${FLOAT_TYPE} compiler)
+    if (PICO_C_COMPILER_IS_GNU)
+        target_compile_options(custom_float_funcs_test_${FLOAT_TYPE} PRIVATE -Wno-analyzer-use-of-uninitialized-value)
+    endif()
     if (PICO_C_COMPILER_IS_CLANG)
         # llvm by default will treat our out of range float->int conversions as undefined behavior
         # and may just decide the function is too broken to bother even with the function epilogue, so we
diff --git a/test/pico_sha256_test/pico_sha256_test.c b/test/pico_sha256_test/pico_sha256_test.c
index 9cd819a..a1bb78d 100644
--- a/test/pico_sha256_test/pico_sha256_test.c
+++ b/test/pico_sha256_test/pico_sha256_test.c
@@ -87,6 +87,7 @@
 
     // nist 3
     uint8_t *buffer = malloc(10000);
+    hard_assert(buffer);
     memset(buffer, 0x61, BUFFER_SIZE);
     const uint8_t nist_3_expected[] = { \
         0xcd, 0xc7, 0x6e, 0x5c, 0x99, 0x14, 0xfb, 0x92, 0x81, 0xa1, \
diff --git a/test/pico_time_test/pico_time_test.c b/test/pico_time_test/pico_time_test.c
index 9ed05e2..b42e16e 100644
--- a/test/pico_time_test/pico_time_test.c
+++ b/test/pico_time_test/pico_time_test.c
@@ -126,8 +126,8 @@
     }
     PICOTEST_CHECK(absolute_time_diff_us(time_base, get_absolute_time()) < init_ms * 1000, "This is a flaky test :-(");
 
-    uint64_t last_fired_at[NUM_ALARMS];
-    uint64_t last_target[NUM_ALARMS];
+    uint64_t last_fired_at[NUM_ALARMS] = {};
+    uint64_t last_target[NUM_ALARMS] = {};
     memset(&last_fired_at, 0, sizeof(last_fired_at));
     printf("Sleeping...\n");
     sleep_us(TEST_LENGTH_US + 250000);