mirror of
https://github.com/libretro/RetroArch
synced 2025-04-10 15:45:19 +00:00
(Widgets) Fix serious heap-use-after-free errors
This commit is contained in:
parent
c63a65ffa5
commit
9bbc9dd30e
@ -2246,12 +2246,19 @@ bool gfx_animation_kill_by_tag(uintptr_t *tag)
|
|||||||
if (!tag || *tag == (uintptr_t)-1)
|
if (!tag || *tag == (uintptr_t)-1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
/* Scan animation list */
|
||||||
for (i = 0; i < da_count(p_anim->list); ++i)
|
for (i = 0; i < da_count(p_anim->list); ++i)
|
||||||
{
|
{
|
||||||
struct tween *t = da_getptr(p_anim->list, i);
|
struct tween *t = da_getptr(p_anim->list, i);
|
||||||
|
|
||||||
if (!t || t->tag != *tag)
|
if (!t || t->tag != *tag)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* If we are currently inside gfx_animation_update(),
|
||||||
|
* we are already looping over p_anim->list entries
|
||||||
|
* > Cannot modify p_anim->list now, so schedule a
|
||||||
|
* delete for when the gfx_animation_update() loop
|
||||||
|
* is complete */
|
||||||
if (p_anim->in_update)
|
if (p_anim->in_update)
|
||||||
{
|
{
|
||||||
t->deleted = true;
|
t->deleted = true;
|
||||||
@ -2264,41 +2271,26 @@ bool gfx_animation_kill_by_tag(uintptr_t *tag)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
/* If we are currently inside gfx_animation_update(),
|
||||||
}
|
* also have to scan *pending* animation list
|
||||||
|
* (otherwise any entries that are simultaneously added
|
||||||
void gfx_animation_kill_by_subject(gfx_animation_ctx_subject_t *subject)
|
* and deleted inside gfx_animation_update() won't get
|
||||||
{
|
* deleted at all, producing utter chaos) */
|
||||||
unsigned i, j, killed = 0;
|
if (p_anim->in_update)
|
||||||
float **sub = (float**)subject->data;
|
|
||||||
gfx_animation_t *p_anim = anim_get_ptr();
|
|
||||||
|
|
||||||
for (i = 0; i < da_count(p_anim->list) && killed < subject->count; ++i)
|
|
||||||
{
|
{
|
||||||
struct tween *t = da_getptr(p_anim->list, i);
|
for (i = 0; i < da_count(p_anim->pending); ++i)
|
||||||
if (!t)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (j = 0; j < subject->count; ++j)
|
|
||||||
{
|
{
|
||||||
if (t->subject != sub[j])
|
struct tween *t = da_getptr(p_anim->pending, i);
|
||||||
|
|
||||||
|
if (!t || t->tag != *tag)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (p_anim->in_update)
|
da_delete(p_anim->pending, i);
|
||||||
{
|
--i;
|
||||||
t->deleted = true;
|
|
||||||
p_anim->pending_deletes = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
da_delete(p_anim->list, i);
|
|
||||||
--i;
|
|
||||||
}
|
|
||||||
|
|
||||||
killed++;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
float gfx_animation_get_delta_time(void)
|
float gfx_animation_get_delta_time(void)
|
||||||
|
@ -100,12 +100,6 @@ enum gfx_animation_ticker_type
|
|||||||
TICKER_TYPE_LAST
|
TICKER_TYPE_LAST
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct gfx_animation_ctx_subject
|
|
||||||
{
|
|
||||||
size_t count;
|
|
||||||
const void *data;
|
|
||||||
} gfx_animation_ctx_subject_t;
|
|
||||||
|
|
||||||
typedef struct gfx_animation_ctx_entry
|
typedef struct gfx_animation_ctx_entry
|
||||||
{
|
{
|
||||||
enum gfx_animation_easing_type easing_enum;
|
enum gfx_animation_easing_type easing_enum;
|
||||||
@ -219,8 +213,6 @@ bool gfx_animation_is_active(void);
|
|||||||
|
|
||||||
bool gfx_animation_kill_by_tag(uintptr_t *tag);
|
bool gfx_animation_kill_by_tag(uintptr_t *tag);
|
||||||
|
|
||||||
void gfx_animation_kill_by_subject(gfx_animation_ctx_subject_t *subject);
|
|
||||||
|
|
||||||
bool gfx_animation_push(gfx_animation_ctx_entry_t *entry);
|
bool gfx_animation_push(gfx_animation_ctx_entry_t *entry);
|
||||||
|
|
||||||
void gfx_animation_push_delayed(unsigned delay, gfx_animation_ctx_entry_t *entry);
|
void gfx_animation_push_delayed(unsigned delay, gfx_animation_ctx_entry_t *entry);
|
||||||
|
@ -2252,6 +2252,16 @@ static void gfx_widgets_free(dispgfx_widget_t *p_dispwidget)
|
|||||||
fifo_read(p_dispwidget->msg_queue,
|
fifo_read(p_dispwidget->msg_queue,
|
||||||
&msg_widget, sizeof(msg_widget));
|
&msg_widget, sizeof(msg_widget));
|
||||||
|
|
||||||
|
/* Note: gfx_widgets_free() is only called when
|
||||||
|
* main_exit() is invoked. At this stage, we cannot
|
||||||
|
* guarantee that any task pointers are valid (the
|
||||||
|
* task may have been free()'d, but we can't know
|
||||||
|
* that here) - so all we can do is unset the task
|
||||||
|
* pointer associated with each message
|
||||||
|
* > If we don't do this, gfx_widgets_msg_queue_free()
|
||||||
|
* will generate heap-use-after-free errors */
|
||||||
|
msg_widget->task_ptr = NULL;
|
||||||
|
|
||||||
gfx_widgets_msg_queue_free(p_dispwidget, msg_widget, false);
|
gfx_widgets_msg_queue_free(p_dispwidget, msg_widget, false);
|
||||||
free(msg_widget);
|
free(msg_widget);
|
||||||
}
|
}
|
||||||
@ -2268,6 +2278,16 @@ static void gfx_widgets_free(dispgfx_widget_t *p_dispwidget)
|
|||||||
menu_widget_msg_t *msg = (menu_widget_msg_t*)
|
menu_widget_msg_t *msg = (menu_widget_msg_t*)
|
||||||
p_dispwidget->current_msgs->list[i].userdata;
|
p_dispwidget->current_msgs->list[i].userdata;
|
||||||
|
|
||||||
|
/* Note: gfx_widgets_free() is only called when
|
||||||
|
* main_exit() is invoked. At this stage, we cannot
|
||||||
|
* guarantee that any task pointers are valid (the
|
||||||
|
* task may have been free()'d, but we can't know
|
||||||
|
* that here) - so all we can do is unset the task
|
||||||
|
* pointer associated with each message
|
||||||
|
* > If we don't do this, gfx_widgets_msg_queue_free()
|
||||||
|
* will generate heap-use-after-free errors */
|
||||||
|
msg->task_ptr = NULL;
|
||||||
|
|
||||||
gfx_widgets_msg_queue_free(p_dispwidget, msg, false);
|
gfx_widgets_msg_queue_free(p_dispwidget, msg, false);
|
||||||
}
|
}
|
||||||
file_list_free(p_dispwidget->current_msgs);
|
file_list_free(p_dispwidget->current_msgs);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user