The slavio_timer device's instance_init function allocates memory for
TimerContext structs and a ptimer, but it never frees this memory, so
we will leak it if the QMP interface does introspection of this
device type, as reported by the clang address sanitizer:

Indirect leak of 4896 byte(s) in 17 object(s) allocated from:
    #0 0x5f2948d9b14d in calloc 
(/home/pm215/qemu/build/san/qemu-system-sparc+0xe0c14d) (BuildId: 
7210711bdf6f7fbd0b863bd2dfcc7c42c7175db1)
    #1 0x758584b11771 in g_malloc0 
(/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x63771) (BuildId: 
116e142b9b52c8a4dfd403e759e71ab8f95d8bb3)
    #2 0x5f2949097b8a in slavio_timer_init 
/home/pm215/qemu/build/san/../../hw/timer/slavio_timer.c:403:14
    #3 0x5f29495d790f in object_initialize_with_type 
/home/pm215/qemu/build/san/../../qom/object.c:570:5
    #4 0x5f29495d96ef in object_new_with_type 
/home/pm215/qemu/build/san/../../qom/object.c:774:5
    #5 0x5f2949a30a26 in qmp_device_list_properties 
/home/pm215/qemu/build/san/../../qom/qom-qmp-cmds.c:206:11

Indirect leak of 1632 byte(s) in 17 object(s) allocated from:
    #0 0x5f2948d9b14d in calloc 
(/home/pm215/qemu/build/san/qemu-system-sparc+0xe0c14d) (BuildId: 
7210711bdf6f7fbd0b863bd2dfcc7c42c7175db1)
    #1 0x758584b11771 in g_malloc0 
(/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x63771) (BuildId: 
116e142b9b52c8a4dfd403e759e71ab8f95d8bb3)
    #2 0x5f2948f7c65a in ptimer_init 
/home/pm215/qemu/build/san/../../hw/core/ptimer.c:464:9
    #3 0x5f2949097c1f in slavio_timer_init 
/home/pm215/qemu/build/san/../../hw/timer/slavio_timer.c:407:32
    #4 0x5f29495d790f in object_initialize_with_type 
/home/pm215/qemu/build/san/../../qom/object.c:570:5
    #5 0x5f29495d96ef in object_new_with_type 
/home/pm215/qemu/build/san/../../qom/object.c:774:5
    #6 0x5f2949a30a26 in qmp_device_list_properties 
/home/pm215/qemu/build/san/../../qom/qom-qmp-cmds.c:206:11

Avoid the TimerContext leaks by making them an array inside the
SLAVIO_TimerState struct instead of allocating a compile-time-fixed
number of them each individually with g_new0() and then throwing away
the pointer.

Avoid the ptimer() leak by calling ptimer_free in
instance_finalize().

Signed-off-by: Peter Maydell <[email protected]>
---
 hw/timer/slavio_timer.c | 25 ++++++++++++++++++-------
 1 file changed, 18 insertions(+), 7 deletions(-)

diff --git a/hw/timer/slavio_timer.c b/hw/timer/slavio_timer.c
index 4a3e227fba..eccdc532fb 100644
--- a/hw/timer/slavio_timer.c
+++ b/hw/timer/slavio_timer.c
@@ -62,20 +62,21 @@ typedef struct CPUTimerState {
 #define TYPE_SLAVIO_TIMER "slavio_timer"
 OBJECT_DECLARE_SIMPLE_TYPE(SLAVIO_TIMERState, SLAVIO_TIMER)
 
+typedef struct TimerContext {
+    MemoryRegion iomem;
+    SLAVIO_TIMERState *s;
+    unsigned int timer_index; /* 0 for system, 1 ... MAX_CPUS for CPU timers */
+} TimerContext;
+
 struct SLAVIO_TIMERState {
     SysBusDevice parent_obj;
 
     uint32_t num_cpus;
     uint32_t cputimer_mode;
     CPUTimerState cputimer[MAX_CPUS + 1];
+    TimerContext timer_context[MAX_CPUS + 1];
 };
 
-typedef struct TimerContext {
-    MemoryRegion iomem;
-    SLAVIO_TIMERState *s;
-    unsigned int timer_index; /* 0 for system, 1 ... MAX_CPUS for CPU timers */
-} TimerContext;
-
 #define SYS_TIMER_SIZE 0x14
 #define CPU_TIMER_SIZE 0x10
 
@@ -400,7 +401,7 @@ static void slavio_timer_init(Object *obj)
         uint64_t size;
         char timer_name[20];
 
-        tc = g_new0(TimerContext, 1);
+        tc = &s->timer_context[i];
         tc->s = s;
         tc->timer_index = i;
 
@@ -420,6 +421,15 @@ static void slavio_timer_init(Object *obj)
     }
 }
 
+static void slavio_timer_finalize(Object *obj)
+{
+    SLAVIO_TIMERState *s = SLAVIO_TIMER(obj);
+
+    for (int i = 0; i <= MAX_CPUS; i++) {
+        ptimer_free(s->cputimer[i].timer);
+    }
+}
+
 static const Property slavio_timer_properties[] = {
     DEFINE_PROP_UINT32("num_cpus",  SLAVIO_TIMERState, num_cpus,  0),
 };
@@ -438,6 +448,7 @@ static const TypeInfo slavio_timer_info = {
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(SLAVIO_TIMERState),
     .instance_init = slavio_timer_init,
+    .instance_finalize = slavio_timer_finalize,
     .class_init    = slavio_timer_class_init,
 };
 
-- 
2.43.0


Reply via email to