[PATCH v2] tcg: Remove NULL arithmetic in tcg_malloc()

Ilya Leoshkevich posted 1 patch 4 months, 4 weeks ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20250618183759.9197-1-iii@linux.ibm.com
Maintainers: Richard Henderson <richard.henderson@linaro.org>, Paolo Bonzini <pbonzini@redhat.com>
include/tcg/tcg.h | 9 ++++-----
tcg/tcg.c         | 3 ++-
2 files changed, 6 insertions(+), 6 deletions(-)
[PATCH v2] tcg: Remove NULL arithmetic in tcg_malloc()
Posted by Ilya Leoshkevich 4 months, 4 weeks ago
Clang 20.1.6 (Fedora 20.1.6-1.fc42)'s UBSAN complains:

    qemu/include/tcg/tcg.h:715:19: runtime error: applying non-zero offset 64 to null pointer

The code uses NULL as pool's initial start and end, with the intention
that `pool_cur + size > pool_end` should trigger the allocation.
Unfortunately C prohibits adding non-zero to NULL, even if the result
is not dereferenced.

Fix by using a dummy pool and change the allocation check to
`pool_end - pool_cur < size`. Both are required, because creating
pointers larger than one past the end of an array is prohibited,
as well as subtracting NULL from NULL.

Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
---

v1: https://lore.kernel.org/qemu-devel/20250618103555.2020-1-iii@linux.ibm.com/
v1 -> v2: Also change the allocation check.

 include/tcg/tcg.h | 9 ++++-----
 tcg/tcg.c         | 3 ++-
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index 125323f153a..4190e8bdbc9 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -706,17 +706,16 @@ size_t tcg_nb_tbs(void);
 static inline void *tcg_malloc(int size)
 {
     TCGContext *s = tcg_ctx;
-    uint8_t *ptr, *ptr_end;
 
     /* ??? This is a weak placeholder for minimum malloc alignment.  */
     size = QEMU_ALIGN_UP(size, 8);
 
-    ptr = s->pool_cur;
-    ptr_end = ptr + size;
-    if (unlikely(ptr_end > s->pool_end)) {
+    if (unlikely(s->pool_end - s->pool_cur < size)) {
         return tcg_malloc_internal(tcg_ctx, size);
     } else {
-        s->pool_cur = ptr_end;
+        uint8_t *ptr = s->pool_cur;
+
+        s->pool_cur += size;
         return ptr;
     }
 }
diff --git a/tcg/tcg.c b/tcg/tcg.c
index d714ae2889c..afcc7ec8849 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1358,13 +1358,14 @@ void *tcg_malloc_internal(TCGContext *s, int size)
 
 void tcg_pool_reset(TCGContext *s)
 {
+    static uint8_t dummy_pool;
     TCGPool *p, *t;
     for (p = s->pool_first_large; p; p = t) {
         t = p->next;
         g_free(p);
     }
     s->pool_first_large = NULL;
-    s->pool_cur = s->pool_end = NULL;
+    s->pool_cur = s->pool_end = &dummy_pool;
     s->pool_current = NULL;
 }
 
-- 
2.49.0