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);