Before this patch, users of the property array would free the
array themselves in their cleanup functions. This causes
inconsistencies where some users leak the array and some free them.
This patch makes it so that the property array's release function
frees the property array (instead of just its elements). It fixes any
leaks and requires less code.
DEFINE_PROP_ARRAY leakers that are fixed in this patch:
ebpf-rss_fds in hw/net/virtio-net.c
rnmi_irqvec, rnmi_excpvec in hw/riscv/riscv_hart.c
common.display_modes in hw/display/apple-gfx-mmio.m
common.display_modes in hw/display/apple-gfx-pci.m
Signed-off-by: Chandan Somani <csomani@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Link: https://lore.kernel.org/r/20260108230311.584141-2-csomani@redhat.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
}
block_acct_add_interval(stats, stats_intervals[i]);
}
- g_free(stats_intervals);
}
return true;
}
/*
* Object property release callback for array properties: We call the
- * underlying element's property release hook for each element.
- *
- * Note that it is the responsibility of the individual device's deinit
- * to free the array proper.
+ * underlying element's property release hook for each element and free the
+ * property array.
*/
static void release_prop_array(Object *obj, const char *name, void *opaque)
{
char *elem = *arrayptr;
int i;
- if (!prop->arrayinfo->release) {
- return;
+ if (prop->arrayinfo->release) {
+ for (i = 0; i < *alenptr; i++) {
+ Property elem_prop = array_elem_prop(obj, prop, name, elem);
+ prop->arrayinfo->release(obj, NULL, &elem_prop);
+ elem += prop->arrayfieldsize;
+ }
}
- for (i = 0; i < *alenptr; i++) {
- Property elem_prop = array_elem_prop(obj, prop, name, elem);
- prop->arrayinfo->release(obj, NULL, &elem_prop);
- elem += prop->arrayfieldsize;
- }
+ g_clear_pointer(arrayptr, g_free);
+ *alenptr = 0;
}
/*
qemu_input_handler_register(dev, &stellaris_gamepad_handler);
}
-static void stellaris_gamepad_finalize(Object *obj)
-{
- StellarisGamepad *s = STELLARIS_GAMEPAD(obj);
-
- g_free(s->keycodes);
-}
-
static void stellaris_gamepad_reset_enter(Object *obj, ResetType type)
{
StellarisGamepad *s = STELLARIS_GAMEPAD(obj);
.name = TYPE_STELLARIS_GAMEPAD,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(StellarisGamepad),
- .instance_finalize = stellaris_gamepad_finalize,
.class_init = stellaris_gamepad_class_init,
},
};
s->itslist = g_ptr_array_new();
}
-static void arm_gicv3_finalize(Object *obj)
-{
- GICv3State *s = ARM_GICV3_COMMON(obj);
-
- g_free(s->redist_region_count);
-}
-
static void arm_gicv3_common_reset_hold(Object *obj, ResetType type)
{
GICv3State *s = ARM_GICV3_COMMON(obj);
.instance_size = sizeof(GICv3State),
.class_size = sizeof(ARMGICv3CommonClass),
.class_init = arm_gicv3_common_class_init,
- .instance_finalize = arm_gicv3_finalize,
.abstract = true,
.interfaces = (const InterfaceInfo[]) {
{ TYPE_ARM_LINUX_BOOT_IF },
sysbus_init_irq(d, &icu->_swi);
}
-static void rxicu_fini(Object *obj)
-{
- RXICUState *icu = RX_ICU(obj);
- g_free(icu->map);
- g_free(icu->init_sense);
-}
-
static const VMStateDescription vmstate_rxicu = {
.name = "rx-icu",
.version_id = 1,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(RXICUState),
.instance_init = rxicu_init,
- .instance_finalize = rxicu_fini,
.class_init = rxicu_class_init,
};
{
arm_sysctl_state *s = ARM_SYSCTL(obj);
- g_free(s->db_voltage);
g_free(s->db_clock);
- g_free(s->db_clock_reset);
}
static const Property arm_sysctl_properties[] = {
s->oscclk = g_new0(uint32_t, s->num_oscclk);
}
-static void mps2_scc_finalize(Object *obj)
-{
- MPS2SCC *s = MPS2_SCC(obj);
-
- g_free(s->oscclk_reset);
-}
-
static bool cfg7_needed(void *opaque)
{
MPS2SCC *s = opaque;
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(MPS2SCC),
.instance_init = mps2_scc_init,
- .instance_finalize = mps2_scc_finalize,
.class_init = mps2_scc_class_init,
};
world_free(r->worlds[i]);
}
}
- g_free(r->fp_ports_peers);
}
static void rocker_reset(DeviceState *dev)
}
}
-static void efuse_finalize(Object *obj)
-{
- XlnxEFuse *s = XLNX_EFUSE(obj);
-
- g_free(s->ro_bits);
-}
-
static void efuse_prop_set_drive(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
.name = TYPE_XLNX_EFUSE,
.parent = TYPE_DEVICE,
.instance_size = sizeof(XlnxEFuse),
- .instance_finalize = efuse_finalize,
.class_init = efuse_class_init,
};
sysbus_init_irq(sbd, &s->irq_efuse_imr);
}
-static void efuse_ctrl_finalize(Object *obj)
-{
- XlnxVersalEFuseCtrl *s = XLNX_VERSAL_EFUSE_CTRL(obj);
-
- g_free(s->extra_pg0_lock_spec);
-}
-
static const VMStateDescription vmstate_efuse_ctrl = {
.name = TYPE_XLNX_VERSAL_EFUSE_CTRL,
.version_id = 1,
.instance_size = sizeof(XlnxVersalEFuseCtrl),
.class_init = efuse_ctrl_class_init,
.instance_init = efuse_ctrl_init,
- .instance_finalize = efuse_ctrl_finalize,
};
static void efuse_ctrl_register_types(void)
TYPE_VIRTIO_IOMMU);
}
-static void virtio_iommu_pci_instance_finalize(Object *obj)
-{
- VirtIOIOMMUPCI *dev = VIRTIO_IOMMU_PCI(obj);
-
- g_free(dev->vdev.prop_resv_regions);
-}
-
static const VirtioPCIDeviceTypeInfo virtio_iommu_pci_info = {
.generic_name = TYPE_VIRTIO_IOMMU_PCI,
.instance_size = sizeof(VirtIOIOMMUPCI),
.instance_init = virtio_iommu_pci_instance_init,
- .instance_finalize = virtio_iommu_pci_instance_finalize,
.class_init = virtio_iommu_pci_class_init,
};