mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-07 08:36:02 -10:00
core_info: gate string_split on strdup success in CCJSONStringHandler
CCJSONStringHandler in core_info.c had an unchecked strdup
whose result fed directly into string_split, which
NULL-derefs on NULL input:
*pCtx->current_string_val = strdup(pValue);
if (pCtx->current_string_list_val)
{
if (*pCtx->current_string_list_val)
string_list_free(*pCtx->current_string_list_val);
*pCtx->current_string_list_val =
string_split(*pCtx->current_string_val, "|");
}
On strdup OOM, *current_string_val = NULL. string_split
in libretro-common/lists/string_list.c does:
struct string_list *string_split(const char *str, const char *delim)
{
const char *p = str;
struct string_list *list = string_list_new();
if (!list)
return NULL;
while (*p) /* NULL-deref on str == NULL */
{
...
There's no NULL-check on str before dereferencing via p. So
strdup OOM -> string_split segfault.
Fix: gate the entire string_split block on
'*pCtx->current_string_val' being non-NULL. Consequence on
OOM: the string_list for this field is not updated
(*current_string_list_val retains its previous value, which
could be NULL if it was never set or a valid list if this
field has been parsed before - either is fine for downstream
consumers, which already NULL-guard the list per the deep-
copy pattern in core_info_copy).
=== Swept-clean in the same pass across small modules ===
- camera/drivers/video4linux2.c (3 sites), pipewire.c (2
sites), ffmpeg.c (1), android.c (1): all NULL-checked.
- record/record_driver.c (1 site) and record/drivers/
record_wav.c / record_ffmpeg.c (1 each): all NULL-checked.
- location/drivers/android.c (1 site): NULL-checked.
- bluetooth/drivers/bluez.c / bluetoothctl.c (1 each):
return calloc() directly without NULL-check, but the caller
in bluetooth/bluetooth_driver.c does
bt_st->data = bt_st->drv->init();
if (!bt_st->data)
bt_st->active = false;
so the NULL return is handled - these driver init functions
are intentionally minimal.
- disk_control.c: zero alloc sites.
- disk_index_file.c (1 site): strdup in DCifJSONStringHandler,
but downstream readers NULL-guard
context.image_path, so strdup failure produces empty
image_path - graceful degradation, not a crash.
- core_info.c other 44 sites: all NULL-checked. Includes the
deep-copy strdups in core_info_copy which use the conditional
'? strdup(src->x) : NULL' pattern (strdup failure produces
NULL, downstream tolerates). core_info_cache_list_new has a
two-stage alloc with proper cleanup. core_info_path_list_
new has bulk NULL-check after four parallel callocs.
- core_updater_list.c (14 sites): all NULL-checked, proper
tmp-pattern reallocs for each remote/local path buffer.
- core_backup.c (4 sites): all NULL-checked.
Reachability: strdup OOM in JSON parsing is rare but possible.
This code path fires during core info parsing at startup - a
failure here would previously crash the core scanner silently
on memory-starved devices; post-patch the scanner continues
with a missing list field.
Thread-safety: core info parsing runs on the core scanner
task thread, single-threaded per scan. No concurrency
concerns.
This commit is contained in:
1 parent
8fd7aa48c6
commit
4e5f06b06b
1 file changed
+9
-1
+9
-1
@@ -307,7 +307,15 @@ static bool CCJSONStringHandler(void *context,
|
||||
free(*pCtx->current_string_val);
|
||||
*pCtx->current_string_val = strdup(pValue);
|
||||
|
||||
if (pCtx->current_string_list_val)
|
||||
/* Gate the string_list split on strdup success: if strdup
|
||||
* returned NULL (OOM), the assignment above stored NULL
|
||||
* into *current_string_val, and string_split dereferences
|
||||
* its first parameter unconditionally at
|
||||
* libretro-common/lists/string_list.c:252 ('while (*p)' with
|
||||
* p = str). On OOM just leave current_string_list_val
|
||||
* alone; downstream core_info readers already tolerate
|
||||
* missing split lists. */
|
||||
if (pCtx->current_string_list_val && *pCtx->current_string_val)
|
||||
{
|
||||
if (*pCtx->current_string_list_val)
|
||||
string_list_free(*pCtx->current_string_list_val);
|
||||
|
||||
Reference in new issue
Block a user