Commit bcb54e5
committed
tasks/task_audio_mixer: drop needless strdup+free of basename in 10 upload handlers
task_audio_mixer_handle_upload_* functions (10 variants: ogg,
ogg_and_play, wav, wav_and_play, flac, flac_and_play, mp3,
mp3_and_play, mod, mod_and_play) all shared the same pattern:
params.basename = (img->path && *img->path)
? strdup(path_basename_nocompression(img->path))
: NULL;
audio_driver_mixer_add_stream(¶ms);
if (img->path)
free(img->path);
if (params.basename != NULL)
free(params.basename);
free(img);
free(user_data);
The strdup + matching free form a redundant round-trip:
1. path_basename_nocompression(img->path) returns a pointer
INTO img->path (the basename portion within the full path
string). No allocation - it's just a pointer walk that
finds the last '/' and returns what follows.
2. strdup copies that into a fresh heap buffer B.
3. audio_driver_mixer_add_stream is called synchronously.
Its only use of params->basename is at audio_driver.c:1508
audio_driver_st.mixer_streams[free_slot].name =
(params->basename && *params->basename)
? strdup(params->basename)
: NULL;
which immediately strdups it into its own owned buffer C
for long-term storage in mixer_streams[slot].name.
4. add_stream returns.
5. free(B) - releases the temporary we just made.
6. free(img->path) - releases the original string (which the
path_basename_nocompression pointer aliased into).
So B existed purely to bridge the basename's content from
img->path (alive through step 6) into mixer_streams[slot].name
(owned by add_stream via its own strdup at step 3). We can
skip step 2 and step 5 entirely - pass the aliased pointer
directly into params.basename. add_stream's strdup at step 3
captures the content before step 6 frees the backing string,
so the aliased-pointer lifetime is valid for its one and only
read.
params.basename = (img->path && *img->path)
? (char*)path_basename_nocompression(img->path)
: NULL;
audio_driver_mixer_add_stream(¶ms);
if (img->path)
free(img->path);
free(img);
free(user_data);
The cast to (char*) is because path_basename_nocompression
returns const char* but the params.basename field is non-const
char*. The non-const is vestigial from when the field was
owning - add_stream never writes through it, only reads it
once before strdup'ing.
=== Savings ===
Per audio mixer upload: 1 strdup + 1 free eliminated.
Across 10 upload handlers (ogg/wav/flac/mp3/mod x and_play
variants), 20 operations removed, -20 lines of code.
The strdup overhead is O(basename_length) - small per call,
but this fires on every cheevo unlock sound, menu BGM load,
configurable hint sound, etc. On memory-constrained embedded
targets (Vita, 3DS, classic consoles) every saved malloc
helps with heap fragmentation.
=== Correctness analysis ===
Traced the full img pointer lifetime for every handler:
- task_data is (nbio_buf_t*)task_data, created by the NBIO
file-read task. The handler takes ownership via
task->handler's task_data transfer.
- img->path is a heap string owned by img.
- path_basename_nocompression(img->path) returns a pointer
that shares lifetime with img->path.
- audio_driver_mixer_add_stream is synchronous - no
reentrant task dispatch, no storage of params->basename
beyond the strdup at line 1508.
- After add_stream returns, img->path is no longer needed
by anyone downstream. The handler free()s it, then img,
then user_data.
No aliasing hazard, no UAF, no leak. This mirrors the pattern
already used by e.g. params.buf (= img->buf, not strdup'd),
params.bufsize, and the other params fields.
Verified the full chain in audio_driver.c: add_stream reads
params->basename at line 1508 exactly once, strdups it, and
never looks at the pointer again. All return-false paths
above line 1508 never touch basename, so failure modes also
don't create leaks.
=== Swept-clean in the same pass ===
Looked for the same pattern elsewhere:
- core_backup.c:381 'strdup(path_basename(backup_path))'
is NOT a candidate - subsequent path_remove_extension()
modifies the string in place, so we need our own mutable
copy. Correct as-is.
- No other strdup(path_basename(...)) patterns in the
RetroArch-owned code (deps/ and libretro-common/ not
scanned, those have their own ownership conventions).
Scope: local to task_audio_mixer.c. No API changes, no
header changes. audio_driver_mixer_add_stream's contract
on params->basename is unchanged (it still only reads it
once via strdup).
Thread-safety: all handlers run on the main task dispatch
thread. No concurrency concerns.1 parent 60bda54 commit bcb54e5
1 file changed
Lines changed: 10 additions & 30 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
115 | 115 | | |
116 | 116 | | |
117 | 117 | | |
118 | | - | |
| 118 | + | |
119 | 119 | | |
120 | 120 | | |
121 | 121 | | |
122 | 122 | | |
123 | 123 | | |
124 | | - | |
125 | | - | |
126 | 124 | | |
127 | 125 | | |
128 | 126 | | |
| |||
146 | 144 | | |
147 | 145 | | |
148 | 146 | | |
149 | | - | |
| 147 | + | |
150 | 148 | | |
151 | 149 | | |
152 | 150 | | |
153 | 151 | | |
154 | 152 | | |
155 | | - | |
156 | | - | |
157 | 153 | | |
158 | 154 | | |
159 | 155 | | |
| |||
177 | 173 | | |
178 | 174 | | |
179 | 175 | | |
180 | | - | |
| 176 | + | |
181 | 177 | | |
182 | 178 | | |
183 | 179 | | |
184 | 180 | | |
185 | 181 | | |
186 | | - | |
187 | | - | |
188 | 182 | | |
189 | 183 | | |
190 | 184 | | |
| |||
208 | 202 | | |
209 | 203 | | |
210 | 204 | | |
211 | | - | |
| 205 | + | |
212 | 206 | | |
213 | 207 | | |
214 | 208 | | |
215 | 209 | | |
216 | 210 | | |
217 | | - | |
218 | | - | |
219 | 211 | | |
220 | 212 | | |
221 | 213 | | |
| |||
239 | 231 | | |
240 | 232 | | |
241 | 233 | | |
242 | | - | |
| 234 | + | |
243 | 235 | | |
244 | 236 | | |
245 | 237 | | |
246 | 238 | | |
247 | 239 | | |
248 | | - | |
249 | | - | |
250 | 240 | | |
251 | 241 | | |
252 | 242 | | |
| |||
270 | 260 | | |
271 | 261 | | |
272 | 262 | | |
273 | | - | |
| 263 | + | |
274 | 264 | | |
275 | 265 | | |
276 | 266 | | |
277 | 267 | | |
278 | 268 | | |
279 | | - | |
280 | | - | |
281 | 269 | | |
282 | 270 | | |
283 | 271 | | |
| |||
301 | 289 | | |
302 | 290 | | |
303 | 291 | | |
304 | | - | |
| 292 | + | |
305 | 293 | | |
306 | 294 | | |
307 | 295 | | |
308 | 296 | | |
309 | 297 | | |
310 | | - | |
311 | | - | |
312 | 298 | | |
313 | 299 | | |
314 | 300 | | |
| |||
332 | 318 | | |
333 | 319 | | |
334 | 320 | | |
335 | | - | |
| 321 | + | |
336 | 322 | | |
337 | 323 | | |
338 | 324 | | |
339 | 325 | | |
340 | 326 | | |
341 | | - | |
342 | | - | |
343 | 327 | | |
344 | 328 | | |
345 | 329 | | |
| |||
364 | 348 | | |
365 | 349 | | |
366 | 350 | | |
367 | | - | |
| 351 | + | |
368 | 352 | | |
369 | 353 | | |
370 | 354 | | |
371 | 355 | | |
372 | 356 | | |
373 | | - | |
374 | | - | |
375 | 357 | | |
376 | 358 | | |
377 | 359 | | |
| |||
395 | 377 | | |
396 | 378 | | |
397 | 379 | | |
398 | | - | |
| 380 | + | |
399 | 381 | | |
400 | 382 | | |
401 | 383 | | |
402 | 384 | | |
403 | 385 | | |
404 | | - | |
405 | | - | |
406 | 386 | | |
407 | 387 | | |
408 | 388 | | |
| |||
0 commit comments