Commit f07549b
committed
overlay: fix OOM crash cascade across task_overlay producer and input_driver consumer
Four bugs forming one OOM cascade in the input-overlay load
pipeline. Fixing any one of them in isolation just pushes the
crash one call-frame deeper; they have to land together.
=== tasks/task_overlay.c: task_overlay_desc_populate_eightway_config ===
desc->eightway_config = (overlay_eightway_config_t *)
calloc(1, sizeof(overlay_eightway_config_t));
eightway = desc->eightway_config;
switch (desc->type)
{
case OVERLAY_TYPE_DPAD_AREA:
BIT256_SET(eightway->up, ...); /* NULL-deref */
...
Unchecked calloc; the BIT256_SET writes in the switch body
NULL-deref on OOM. void-returning function so we can't signal
failure to the caller directly.
Fix: NULL-check and early return. This leaves
desc->eightway_config = NULL for an area-type desc that needs
it, which then fires the consumer bug below.
=== input/input_driver.c: input_overlay_poll eightway dispatch ===
case OVERLAY_TYPE_DPAD_AREA:
case OVERLAY_TYPE_ABXY_AREA:
input_overlay_get_eightway_state(
desc, desc->eightway_config,
&out->buttons, x_dist, y_dist);
break;
input_overlay_get_eightway_state dereferences eightway->
slope_high unconditionally (line ~2781). With the producer fix
above leaving eightway_config NULL under OOM, this dispatch path
needs to gate on non-NULL:
if (desc->eightway_config)
input_overlay_get_eightway_state(...);
User-visible consequence on OOM: the one area whose config alloc
failed is dead until overlay reload. Strictly better than a
segfault on the next touch input.
=== tasks/task_overlay.c: task_overlay_handler data alloc ===
overlay_task_data_t *data = (overlay_task_data_t*)
calloc(1, sizeof(*data));
data->overlays = loader->overlays; /* NULL-deref */
...
Unchecked calloc in the task's 'finished and not cancelled'
branch; the seven field writes below NULL-deref on OOM.
Fix: NULL-check and early return (skip the task_set_data call).
The consumer (input_overlay_loaded in input/input_driver.c) then
sees NULL task_data, which cascades to the next bug.
=== input/input_driver.c: input_overlay_loaded task_data and ol allocs ===
overlay_task_data_t *data = (overlay_task_data_t*)task_data;
...
if (err)
return;
ol = (input_overlay_t*)calloc(1, sizeof(*ol));
ol->overlays = data->overlays; /* NULL-deref */
...
Two stacked bugs:
1. task_data can be NULL (from the producer fix above) but is
dereferenced as data->overlays on the very next usable line.
Add an early return.
2. The ol calloc is unchecked. The field writes below NULL-deref
on OOM. Unlike typical OOM-bail patterns, bailing here has a
non-trivial cleanup obligation: task_data was transferred to
us by the retro_task framework and we own it, *and* the
image_list inside it has heap texture_image attachments on
each entry's .attr.p that the success path would transfer
into ol->images via input_overlay_loaded_move_images. Since
ol doesn't exist, we need to free each texture explicitly
before string_list_free (string_list_free only frees the
list struct and its entries' .data strings, not the .attr.p
attachments).
Fix both:
if (!data)
return;
ol = (input_overlay_t*)calloc(1, sizeof(*ol));
if (!ol)
{
if (data->image_list)
{
size_t i;
for (i = 0; i < data->image_list->size; i++)
image_texture_free(
(struct texture_image*)data->image_list->elems[i].attr.p);
string_list_free(data->image_list);
}
free(data);
return;
}
=== Thread-safety ===
task_overlay_handler runs on the retro_task worker thread pool;
input_overlay_loaded runs on the main thread as the task's
completion callback. The ownership transfer of task_data via
task_set_data is already correct (producer populates, consumer
frees), so no lock discipline changes.
=== Reachability ===
Overlay loading runs every time the user picks an overlay from
the menu, configures an auto-load overlay, or switches between
overlays (e.g. OSK toggle). On handheld and embedded targets
with the memory pressure typical of running an emulator core +
overlay textures, OOM at any of these four sites is realistic.
=== Scope ===
Left image_transfer / texture loading paths in task_overlay.c
alone (the per-image malloc + image_texture_load calls all
NULL-check and goto their cleanup labels already). The four
fixes here are the OOM sites that didn't have any guard.1 parent 0563af5 commit f07549b
2 files changed
Lines changed: 61 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3032 | 3032 | | |
3033 | 3033 | | |
3034 | 3034 | | |
3035 | | - | |
3036 | | - | |
3037 | | - | |
| 3035 | + | |
| 3036 | + | |
| 3037 | + | |
| 3038 | + | |
| 3039 | + | |
| 3040 | + | |
| 3041 | + | |
| 3042 | + | |
| 3043 | + | |
| 3044 | + | |
3038 | 3045 | | |
3039 | 3046 | | |
3040 | 3047 | | |
| |||
6220 | 6227 | | |
6221 | 6228 | | |
6222 | 6229 | | |
| 6230 | + | |
| 6231 | + | |
| 6232 | + | |
| 6233 | + | |
| 6234 | + | |
| 6235 | + | |
| 6236 | + | |
| 6237 | + | |
6223 | 6238 | | |
| 6239 | + | |
| 6240 | + | |
| 6241 | + | |
| 6242 | + | |
| 6243 | + | |
| 6244 | + | |
| 6245 | + | |
| 6246 | + | |
| 6247 | + | |
| 6248 | + | |
| 6249 | + | |
| 6250 | + | |
| 6251 | + | |
| 6252 | + | |
| 6253 | + | |
| 6254 | + | |
| 6255 | + | |
| 6256 | + | |
| 6257 | + | |
| 6258 | + | |
| 6259 | + | |
6224 | 6260 | | |
6225 | 6261 | | |
6226 | 6262 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
231 | 231 | | |
232 | 232 | | |
233 | 233 | | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
234 | 246 | | |
235 | 247 | | |
236 | 248 | | |
| |||
1111 | 1123 | | |
1112 | 1124 | | |
1113 | 1125 | | |
| 1126 | + | |
| 1127 | + | |
| 1128 | + | |
| 1129 | + | |
| 1130 | + | |
| 1131 | + | |
| 1132 | + | |
| 1133 | + | |
| 1134 | + | |
| 1135 | + | |
1114 | 1136 | | |
1115 | 1137 | | |
1116 | 1138 | | |
| |||
0 commit comments