@samitouri / QOSamiQemu / commits / 74bb6fb293

audio-be: add common pre-conditions

assert() on valid values, and handle acceptable NULL arguments gracefully. Note audio_driver_write() and audio_driver_read() used to return size (with a "XXX: Consider options") when sw was NULL. Imho, it is more correct to not pretend to have read/written anything by default in the AudioBackend base abstract class. Reviewed-by: Mark Cave-Ayland <mark.caveayland@nutanix.com> Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>

Marc-André Lureau committed Nov 19, 2025 at 11:43 UTC 74bb6fb293e667154048835fe632c47f197a3f2d
2 files changed +64 -5
audio/audio-be.c
+61
@@ -29,6 +29,10 @@ SWVoiceIn *audio_be_open_in(
29 {
30 AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
31
32 + assert(name != NULL);
33 + assert(callback_fn != NULL);
34 + assert(as != NULL);
35 +
36 return klass->open_in(be, sw, name, callback_opaque, callback_fn, as);
37 }
38
@@ -42,6 +46,10 @@ SWVoiceOut *audio_be_open_out(
46 {
47 AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
48
49 + assert(name != NULL);
50 + assert(callback_fn != NULL);
51 + assert(as != NULL);
52 +
53 return klass->open_out(be, sw, name, callback_opaque, callback_fn, as);
54 }
55
@@ -49,6 +57,10 @@ void audio_be_close_out(AudioBackend *be, SWVoiceOut *sw)
57 {
58 AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
59
60 + if (!sw) {
61 + return;
62 + }
63 +
64 return klass->close_out(be, sw);
65 }
66
@@ -56,6 +68,10 @@ void audio_be_close_in(AudioBackend *be, SWVoiceIn *sw)
68 {
69 AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
70
71 + if (!sw) {
72 + return;
73 + }
74 +
75 return klass->close_in(be, sw);
76 }
77
@@ -63,6 +79,10 @@ bool audio_be_is_active_out(AudioBackend *be, SWVoiceOut *sw)
79 {
80 AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
81
82 + if (!sw) {
83 + return false;
84 + }
85 +
86 return klass->is_active_out(be, sw);
87 }
88
@@ -70,6 +90,10 @@ bool audio_be_is_active_in(AudioBackend *be, SWVoiceIn *sw)
90 {
91 AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
92
93 + if (!sw) {
94 + return false;
95 + }
96 +
97 return klass->is_active_in(be, sw);
98 }
99
@@ -77,6 +101,10 @@ size_t audio_be_write(AudioBackend *be, SWVoiceOut *sw, void *buf, size_t size)
101 {
102 AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
103
104 + if (!sw) {
105 + return 0;
106 + }
107 +
108 return klass->write(be, sw, buf, size);
109 }
110
@@ -84,6 +112,10 @@ size_t audio_be_read(AudioBackend *be, SWVoiceIn *sw, void *buf, size_t size)
112 {
113 AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
114
115 + if (!sw) {
116 + return 0;
117 + }
118 +
119 return klass->read(be, sw, buf, size);
120 }
121
@@ -91,6 +123,10 @@ int audio_be_get_buffer_size_out(AudioBackend *be, SWVoiceOut *sw)
123 {
124 AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
125
126 + if (!sw) {
127 + return 0;
128 + }
129 +
130 return klass->get_buffer_size_out(be, sw);
131 }
132
@@ -98,6 +134,10 @@ void audio_be_set_active_out(AudioBackend *be, SWVoiceOut *sw, bool on)
134 {
135 AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
136
137 + if (!sw) {
138 + return;
139 + }
140 +
141 return klass->set_active_out(be, sw, on);
142 }
143
@@ -105,6 +145,10 @@ void audio_be_set_active_in(AudioBackend *be, SWVoiceIn *sw, bool on)
145 {
146 AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
147
148 + if (!sw) {
149 + return;
150 + }
151 +
152 return klass->set_active_in(be, sw, on);
153 }
154
@@ -112,6 +156,10 @@ void audio_be_set_volume_out(AudioBackend *be, SWVoiceOut *sw, Volume *vol)
156 {
157 AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
158
159 + if (!sw) {
160 + return;
161 + }
162 +
163 klass->set_volume_out(be, sw, vol);
164 }
165
@@ -119,6 +167,10 @@ void audio_be_set_volume_in(AudioBackend *be, SWVoiceIn *sw, Volume *vol)
167 {
168 AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
169
170 + if (!sw) {
171 + return;
172 + }
173 +
174 klass->set_volume_in(be, sw, vol);
175 }
176
@@ -130,6 +182,9 @@ CaptureVoiceOut *audio_be_add_capture(
182 {
183 AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
184
185 + assert(as != NULL);
186 + assert(ops != NULL);
187 +
188 return klass->add_capture(be, as, ops, cb_opaque);
189 }
190
@@ -137,6 +192,10 @@ void audio_be_del_capture(AudioBackend *be, CaptureVoiceOut *cap, void *cb_opaqu
192 {
193 AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
194
195 + if (!cap) {
196 + return;
197 + }
198 +
199 klass->del_capture(be, cap, cb_opaque);
200 }
201
@@ -155,6 +214,8 @@ bool audio_be_set_dbus_server(AudioBackend *be,
214 {
215 AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
216
217 + assert(server != NULL);
218 +
219 if (!audio_be_can_set_dbus_server(be)) {
220 error_setg(errp, "Audiodev '%s' is not compatible with DBus",
221 audio_be_get_id(be));
tests/audio/test-audio.c
+3 -5
@@ -493,11 +493,9 @@ static void test_audio_null_handling(void)
493 /* audio_be_get_buffer_size_out(NULL) should return 0 */
494 g_assert_cmpint(audio_be_get_buffer_size_out(be, NULL), ==, 0);
495
496 - /* audio_be_write/read(NULL, ...) should return size (no-op) */
497 - g_assert_cmpuint(audio_be_write(be, NULL, buffer, sizeof(buffer)), ==,
498 - sizeof(buffer));
499 - g_assert_cmpuint(audio_be_read(be, NULL, buffer, sizeof(buffer)), ==,
500 - sizeof(buffer));
496 + /* audio_be_write/read(NULL, ...) should return 0 */
497 + g_assert_cmpuint(audio_be_write(be, NULL, buffer, sizeof(buffer)), ==, 0);
498 + g_assert_cmpuint(audio_be_read(be, NULL, buffer, sizeof(buffer)), ==, 0);
499
500 /* These should not crash */
501 audio_be_set_active_out(be, NULL, true);