Fix T44376: Buttons context, invalid data access

Removing a scene from the buttons window would crash from a Python operator.
This commit is contained in:
Campbell Barton 2015-05-04 15:07:24 +10:00
parent 8d5e57748a
commit 77e6a001a9
Notes: blender-bot 2023-02-14 19:57:33 +01:00
Referenced by issue blender/blender-addons#44376, Delete scene operator used in script crashes blender
Referenced by issue blender/blender-addons#44376, Delete scene operator used in script crashes blender
9 changed files with 71 additions and 1 deletions

View File

@ -273,6 +273,9 @@ void BKE_spacedata_freelist(ListBase *lb);
void BKE_spacedata_copylist(ListBase *lb1, ListBase *lb2);
void BKE_spacedata_draw_locks(int set);
void BKE_spacedata_callback_id_unref_set(void (*func)(struct SpaceLink *sl, const struct ID *));
void BKE_spacedata_id_unref(struct SpaceLink *sl, const struct ID *id);
/* area/regions */
struct ARegion *BKE_area_region_copy(struct SpaceType *st, struct ARegion *ar);
void BKE_area_region_free(struct SpaceType *st, struct ARegion *ar);

View File

@ -82,6 +82,7 @@
#include "BKE_paint.h"
#include "BKE_rigidbody.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
#include "BKE_sequencer.h"
#include "BKE_sound.h"
#include "BKE_unit.h"
@ -823,6 +824,8 @@ static void scene_unlink_space_buts(SpaceButs *sbuts, Scene *sce)
if (sbuts->pinid == &sce->id) {
sbuts->pinid = NULL;
}
BKE_spacedata_id_unref((SpaceLink *)sbuts, &sce->id);
}
void BKE_scene_unlink(Main *bmain, Scene *sce, Scene *newsce)

View File

@ -272,6 +272,19 @@ void BKE_spacedata_draw_locks(int set)
}
}
static void (*spacedata_id_unref_cb)(struct SpaceLink *sl, const struct ID *id) = NULL;
void BKE_spacedata_callback_id_unref_set(void (*func)(struct SpaceLink *sl, const struct ID *))
{
spacedata_id_unref_cb = func;
}
void BKE_spacedata_id_unref(struct SpaceLink *sl, const struct ID *id)
{
if (spacedata_id_unref_cb) {
spacedata_id_unref_cb(sl, id);
}
}
/* not region itself */
void BKE_area_region_free(SpaceType *st, ARegion *ar)

View File

@ -37,4 +37,6 @@ bool ED_texture_context_check_particles(const struct bContext *C);
bool ED_texture_context_check_linestyle(const struct bContext *C);
bool ED_texture_context_check_others(const struct bContext *C);
void ED_buttons_id_unref(struct SpaceButs *sbuts, const struct ID *id);
#endif /* __ED_BUTTONS_H__ */

View File

@ -76,7 +76,6 @@ void ED_region_visible_rect(struct ARegion *ar, struct rcti *rect);
void ED_spacetypes_keymap(struct wmKeyConfig *keyconf);
int ED_area_header_switchbutton(const struct bContext *C, struct uiBlock *block, int yco);
/* areas */
void ED_area_initialize(struct wmWindowManager *wm, struct wmWindow *win, struct ScrArea *sa);
void ED_area_exit(struct bContext *C, struct ScrArea *sa);

View File

@ -42,6 +42,8 @@ void ED_editors_exit(struct bContext *C);
bool ED_editors_flush_edits(const struct bContext *C, bool for_render);
void ED_spacedata_id_unref(struct SpaceLink *sl, const struct ID *id);
/* ************** Undo ************************ */
/* undo.c */

View File

@ -59,6 +59,7 @@
#include "RNA_access.h"
#include "ED_buttons.h"
#include "ED_armature.h"
#include "ED_screen.h"
#include "ED_physics.h"
@ -1179,3 +1180,28 @@ ID *buttons_context_id_path(const bContext *C)
return NULL;
}
void ED_buttons_id_unref(SpaceButs *sbuts, const ID *id)
{
if (sbuts->path) {
ButsContextPath *path = sbuts->path;
int i;
for (i = 0; i < path->len; i++) {
if (path->ptr[i].id.data == id) {
break;
}
}
if (i == path->len) {
/* pass */
}
else if (i == 0) {
MEM_SAFE_FREE(sbuts->path);
}
else {
memset(&path->ptr[i], 0, sizeof(path->ptr[i]) * (path->len - i));
path->len = i;
}
}
}

View File

@ -38,6 +38,7 @@
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_scene_types.h"
#include "DNA_packedFile_types.h"
@ -58,9 +59,11 @@
#include "BKE_paint.h"
#include "ED_armature.h"
#include "ED_buttons.h"
#include "ED_image.h"
#include "ED_mesh.h"
#include "ED_object.h"
#include "ED_outliner.h"
#include "ED_paint.h"
#include "ED_space_api.h"
#include "ED_util.h"
@ -318,3 +321,21 @@ void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *ar, void *arg_info
glEnd();
setlinestyle(0);
}
/**
* Use to free ID references within runtime data (stored outside of DNA)
*
* \note Typically notifiers take care of this,
* but there are times we have to free references immediately, see: T44376
*/
void ED_spacedata_id_unref(struct SpaceLink *sl, const ID *id)
{
switch (sl->spacetype) {
case SPACE_OUTLINER:
ED_outliner_id_unref((SpaceOops *)sl, id);
break;
case SPACE_BUTS:
ED_buttons_id_unref((SpaceButs *)sl, id);
break;
}
}

View File

@ -153,6 +153,7 @@ void WM_init(bContext *C, int argc, const char **argv)
BKE_library_callback_free_notifier_reference_set(WM_main_remove_notifier_reference); /* library.c */
BKE_library_callback_free_editor_id_reference_set(WM_main_remove_editor_id_reference); /* library.c */
BKE_blender_callback_test_break_set(wm_window_testbreak); /* blender.c */
BKE_spacedata_callback_id_unref_set(ED_spacedata_id_unref); /* screen.c */
DAG_editors_update_cb(ED_render_id_flush_update, ED_render_scene_update); /* depsgraph.c */
ED_spacetypes_init(); /* editors/space_api/spacetype.c */