On 13/05/2025 07:14, Volker Rümelin wrote:

Am 11.05.25 um 13:52 schrieb Mark Cave-Ayland:
On 11/05/2025 08:38, Volker Rümelin wrote:

AUD_open_out() may fail and return NULL. This may then lead to
a segmentation fault in memset() below. The memset() behaviour
is undefined if the pointer to the destination object is a null
pointer.

Add the missing error handling code.

Signed-off-by: Volker Rümelin <vr_q...@t-online.de>
---
   hw/audio/asc.c | 7 +++++++
   1 file changed, 7 insertions(+)

diff --git a/hw/audio/asc.c b/hw/audio/asc.c
index 18382ccf6a..03dee0fcc7 100644
--- a/hw/audio/asc.c
+++ b/hw/audio/asc.c
@@ -12,6 +12,7 @@
     #include "qemu/osdep.h"
   #include "qemu/timer.h"
+#include "qapi/error.h"
   #include "hw/sysbus.h"
   #include "hw/irq.h"
   #include "audio/audio.h"
@@ -653,6 +654,12 @@ static void asc_realize(DeviceState *dev, Error
**errp)
         s->voice = AUD_open_out(&s->card, s->voice, "asc.out", s,
asc_out_cb,
                               &as);
+    if (!s->voice) {
+        asc_unrealize(dev);

I don't think it is ever right for a device to unrealize itself. If
the aim is to handle cleanup, then since s->mixbuf and s->silentbuf
are yet to be allocated by this point then I think you can simply call
error_setg() and return.

Hi Mark,

yes my aim was to handle cleanup. When calling asc_unrealize() I don't
have to think about which steps are necessary. In this case I would have
to call AUD_remove_card(&s->card). Therefore, I would like to keep my
patch version.

Hi Volker,

I can see why you want to call a single routine to handle tidy-up, however it is still expected that the various qdev device callbacks are only called internally by the qdev APIs. For example when debugging lifecycle issues you typically put breakpoints on init/realize/unrealize/finalize to figure out why something is not working as expected.

A common example of this is reset in that a chip can be reset by qdev, but also by writing to a reset register via MMIO: in this case both the Resettable interface and the MMIO access simply call the same internal reset function.

You could have a separate cleanup function and call it for the error case here, but since the qdev device callbacks are called in a strict order, you can guarantee that s->mixbuf and s->silentbuf will be unset at this point. So it's probably easiest just to call AUD_remove_card(&s->card) before the return and that guarantees that you won't interfere with any internal qdev management logic.


ATB,

Mark.


Reply via email to