Commit 6cf158d
committed
libretro-common/lists/string_list: fail string_list_clone on inner malloc OOM
Pre-patch: if per-element data malloc failed partway through the
clone loop, the inner branch was:
if (slen != 0)
{
char *ret = (char*)malloc(slen + 1);
if (ret)
{
memcpy(ret, _src, slen + 1);
dest->elems[i].data = ret;
}
}
On OOM, dest->elems[i].data silently stayed NULL (pre-set at the
top of the iteration) and the loop continued. The final return
handed back a list with dest->size set to src->size but some
.data pointers NULL.
This trap fires on every downstream consumer that assumes .data
is non-NULL, which is all of them:
* string_list_find_elem at line 349 dereferences elems[i].data
unconditionally in the (*p1 | 32) compare.
* string_list_join_concat at line 200 strlcpy's from .data;
strlcpy(dst, NULL, ...) is UB (EFAULT on glibc, crash
elsewhere).
* string_list_join_concat_special at line 214 - same.
* string_list_find_elem_prefix at line 377 - tolower on *data.
Empty-string list entries are represented with slen == 0 and
never enter the malloc branch, so a NULL .data after the loop
unambiguously means 'OOM happened here' rather than 'this was
intended to be empty'.
Fix: on malloc failure, tear down everything we've allocated so
far (the j < i .data buffers, the elems array, the dest
struct) and return NULL. Callers of string_list_clone already
handle NULL returns:
* core_info.c clones eight lists with the pattern
'dst->x = src->x ? string_list_clone(src->x) : NULL',
treating NULL as valid cloned-state.
* audio/drivers/{pipewire,pulse}.c return the clone result
directly; their callers must handle NULL anyway for the
no-devicelist case.
* runahead.c and tasks/task_netplay_find_content.c similarly
assign and later test.
NULL is strictly safer and more informative than a
silently-corrupted list.
Thread-safety: string_list_clone takes a const src and produces
a fresh dest; no shared-state mutations. No lock discipline
changes.
Reachability: every deep-clone of a string_list, which is
common for core_info records and audio device enumerations.
Per-element OOM is realistic on memory-tight platforms
(embedded handhelds, PS2, Vita) where core_info can carry
hundreds of entries each with several sub-lists of
short strings.
Scope: one function, one failure mode. The surrounding
string_list_new, string_list_initialize, and other allocators
in this file were also on my audit list but they're already
NULL-checked properly - verified during this pass, no changes
needed there.1 parent 689fc11 commit 6cf158d
1 file changed
Lines changed: 27 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
431 | 431 | | |
432 | 432 | | |
433 | 433 | | |
434 | | - | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
435 | 452 | | |
436 | | - | |
437 | | - | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
438 | 460 | | |
| 461 | + | |
| 462 | + | |
439 | 463 | | |
440 | 464 | | |
441 | 465 | | |
| |||
0 commit comments