@samitouri / QOSamiQemu / commits / 1e3e1d51e2

hw: Make qdev_get_printable_name() consistently return freeable string

The current implementation of qdev_get_printable_name() sometimes returns a string that must not be freed (vdev->id or the fixed fallback string "<unknown device>" and sometimes returns a string that must be freed (the return value of qdev_get_dev_path()). This forces callers to leak the string in the "must be freed" case. Make the function consistent that it always returns a string that the caller must free, and make the three callsites free it. This fixes leaks like this that show up when running "make check" with the address sanitizer enabled: Direct leak of 13 byte(s) in 1 object(s) allocated from: #0 0x5561de21f293 in malloc (/home/pm215/qemu/build/san/qemu-system-i386+0x1a2d293) (BuildId: 6d6fad7130fd5c8dbbc03401df554f68b8034936) #1 0x767ad7a82ac9 in g_malloc (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x62ac9) (BuildId: 116e142b9b52c8a4dfd403e759e71ab8f95d8bb3) #2 0x5561deaf34f2 in pcibus_get_dev_path /home/pm215/qemu/build/san/../../hw/pci/pci.c:2792:12 #3 0x5561df9d8830 in qdev_get_printable_name /home/pm215/qemu/build/san/../../hw/core/qdev.c:431:24 #4 0x5561deebdca2 in virtio_init_region_cache /home/pm215/qemu/build/san/../../hw/virtio/virtio.c:298:17 #5 0x5561df05f842 in memory_region_write_accessor /home/pm215/qemu/build/san/../../system/memory.c:491:5 #6 0x5561df05ed1b in access_with_adjusted_size /home/pm215/qemu/build/san/../../system/memory.c:567:18 #7 0x5561df05e3fa in memory_region_dispatch_write /home/pm215/qemu/build/san/../../system/memory.c #8 0x5561df0aa805 in address_space_stm_internal /home/pm215/qemu/build/san/../../system/memory_ldst.c.inc:85:13 #9 0x5561df0bcad3 in qtest_process_command /home/pm215/qemu/build/san/../../system/qtest.c:480:13 Cc: qemu-stable@nongnu.org Fixes: e209d4d7a31b9 ("virtio: improve virtqueue mapping error messages") Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-ID: <20260307155046.3940197-3-peter.maydell@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>

Peter Maydell committed Mar 7, 2026 at 15:50 UTC 1e3e1d51e20e8b38efa089bf54b5ee2cbbcca221
3 files changed +27 -5
hw/core/qdev.c
+2 -2
@@ -420,7 +420,7 @@ const char *qdev_get_printable_name(DeviceState *vdev)
420 * names.
421 */
422 if (vdev->id) {
423 - return vdev->id;
423 + return g_strdup(vdev->id);
424 }
425 /*
426 * Fall back to the canonical QOM device path (eg. ID for PCI
@@ -437,7 +437,7 @@ const char *qdev_get_printable_name(DeviceState *vdev)
437 * Final fallback: if all else fails, return a placeholder string.
438 * This ensures the error message always contains a valid string.
439 */
440 - return "<unknown device>";
440 + return g_strdup("<unknown device>");
441 }
442
443 void qdev_add_unplug_blocker(DeviceState *dev, Error *reason)
hw/virtio/virtio.c
+9 -3
@@ -281,10 +281,12 @@ void virtio_init_region_cache(VirtIODevice *vdev, int n)
281 len = address_space_cache_init(&new->desc, vdev->dma_as,
282 addr, size, packed);
283 if (len < size) {
284 + g_autofree const char *devname = qdev_get_printable_name(DEVICE(vdev));
285 +
286 virtio_error(vdev,
287 "Failed to map descriptor ring for device %s: "
288 "invalid guest physical address or corrupted queue setup",
287 - qdev_get_printable_name(DEVICE(vdev)));
289 + devname);
290 goto err_desc;
291 }
292
@@ -292,10 +294,12 @@ void virtio_init_region_cache(VirtIODevice *vdev, int n)
294 len = address_space_cache_init(&new->used, vdev->dma_as,
295 vq->vring.used, size, true);
296 if (len < size) {
297 + g_autofree const char *devname = qdev_get_printable_name(DEVICE(vdev));
298 +
299 virtio_error(vdev,
300 "Failed to map used ring for device %s: "
301 "possible guest misconfiguration or insufficient memory",
298 - qdev_get_printable_name(DEVICE(vdev)));
302 + devname);
303 goto err_used;
304 }
305
@@ -303,10 +307,12 @@ void virtio_init_region_cache(VirtIODevice *vdev, int n)
307 len = address_space_cache_init(&new->avail, vdev->dma_as,
308 vq->vring.avail, size, false);
309 if (len < size) {
310 + g_autofree const char *devname = qdev_get_printable_name(DEVICE(vdev));
311 +
312 virtio_error(vdev,
313 "Failed to map avalaible ring for device %s: "
314 "possible queue misconfiguration or overlapping memory region",
309 - qdev_get_printable_name(DEVICE(vdev)));
315 + devname);
316 goto err_avail;
317 }
318
include/hw/core/qdev.h
+16
@@ -1084,6 +1084,22 @@ extern bool qdev_hot_removed;
1084 * If @dev is NULL or not on a bus, returns NULL.
1085 */
1086 char *qdev_get_dev_path(DeviceState *dev);
1087 +
1088 +/**
1089 + * qdev_get_printable_name: Return human readable name for device
1090 + * @dev: Device to get name of
1091 + *
1092 + * Returns: A newly allocated string containing some human
1093 + * readable name for the device, suitable for printing in
1094 + * user-facing error messages. The function will never return NULL,
1095 + * so the name can be used without further checking or fallbacks.
1096 + *
1097 + * If the device has an explicitly set ID (e.g. by the user on the
1098 + * command line via "-device thisdev,id=myid") this is preferred.
1099 + * Otherwise we try the canonical QOM device path (which will be
1100 + * the PCI ID for PCI devices, for example). If all else fails
1101 + * we will return the placeholder "<unknown device">.
1102 + */
1103 const char *qdev_get_printable_name(DeviceState *dev);
1104
1105 void qbus_set_hotplug_handler(BusState *bus, Object *handler);