@samitouri / QOSamiQemu / commits / c9949c096b

hw/timer/slavio_timer: Free resources allocated in instance_init

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 <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Message-ID: <20260307112931.3322532-4-peter.maydell@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>

Peter Maydell committed Mar 7, 2026 at 11:29 UTC c9949c096b2b89a1b118bf483e575ae9c403deb9
1 file changed +18 -7
hw/timer/slavio_timer.c
+18 -7
@@ -62,20 +62,21 @@ typedef struct CPUTimerState {
62 #define TYPE_SLAVIO_TIMER "slavio_timer"
63 OBJECT_DECLARE_SIMPLE_TYPE(SLAVIO_TIMERState, SLAVIO_TIMER)
64
65 +typedef struct TimerContext {
66 + MemoryRegion iomem;
67 + SLAVIO_TIMERState *s;
68 + unsigned int timer_index; /* 0 for system, 1 ... MAX_CPUS for CPU timers */
69 +} TimerContext;
70 +
71 struct SLAVIO_TIMERState {
72 SysBusDevice parent_obj;
73
74 uint32_t num_cpus;
75 uint32_t cputimer_mode;
76 CPUTimerState cputimer[MAX_CPUS + 1];
77 + TimerContext timer_context[MAX_CPUS + 1];
78 };
79
73 -typedef struct TimerContext {
74 - MemoryRegion iomem;
75 - SLAVIO_TIMERState *s;
76 - unsigned int timer_index; /* 0 for system, 1 ... MAX_CPUS for CPU timers */
77 -} TimerContext;
78 -
80 #define SYS_TIMER_SIZE 0x14
81 #define CPU_TIMER_SIZE 0x10
82
@@ -400,7 +401,7 @@ static void slavio_timer_init(Object *obj)
401 uint64_t size;
402 char timer_name[20];
403
403 - tc = g_new0(TimerContext, 1);
404 + tc = &s->timer_context[i];
405 tc->s = s;
406 tc->timer_index = i;
407
@@ -420,6 +421,15 @@ static void slavio_timer_init(Object *obj)
421 }
422 }
423
424 +static void slavio_timer_finalize(Object *obj)
425 +{
426 + SLAVIO_TIMERState *s = SLAVIO_TIMER(obj);
427 +
428 + for (int i = 0; i <= MAX_CPUS; i++) {
429 + ptimer_free(s->cputimer[i].timer);
430 + }
431 +}
432 +
433 static const Property slavio_timer_properties[] = {
434 DEFINE_PROP_UINT32("num_cpus", SLAVIO_TIMERState, num_cpus, 0),
435 };
@@ -438,6 +448,7 @@ static const TypeInfo slavio_timer_info = {
448 .parent = TYPE_SYS_BUS_DEVICE,
449 .instance_size = sizeof(SLAVIO_TIMERState),
450 .instance_init = slavio_timer_init,
451 + .instance_finalize = slavio_timer_finalize,
452 .class_init = slavio_timer_class_init,
453 };
454