[Bf-blender-cvs] [122e2b4] master: Fix T37709: Memory corruption when freeing custom bone shape objects

Sergey Sharybin noreply at git.blender.org
Wed Dec 25 12:53:05 CET 2013


Commit: 122e2b4bfa0211676042ba8e02570d1dcd2fc40d
Author: Sergey Sharybin
Date:   Wed Dec 25 16:43:26 2013 +0600
https://developer.blender.org/rB122e2b4bfa0211676042ba8e02570d1dcd2fc40d

Fix T37709: Memory corruption when freeing custom bone shape objects

Summary:
Issue was caused by access to pchan->custom object from channel free
function when freeing all objects from main. Order of objects free
is not defined and such an access might easily end up with access
to freed memory.

We don't need to do user counter stuff when freeing main, so added
an _ex functions with do_id_user flag which is used when freeing main.

We had the same issue with other datablocks, so now it should be
easier to support relevant user counter.

This issue was caused by the fix for T36391, so perhaps that's indeed
high time to do real user counter.

Reviewers: brecht, campbellbarton

Reviewed By: campbellbarton

Maniphest Tasks: T37709

Differential Revision: https://developer.blender.org/D137

===================================================================

M	source/blender/blenkernel/BKE_action.h
M	source/blender/blenkernel/BKE_library.h
M	source/blender/blenkernel/BKE_object.h
M	source/blender/blenkernel/intern/action.c
M	source/blender/blenkernel/intern/library.c
M	source/blender/blenkernel/intern/object.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h
index 3ac5c8c..9068be9 100644
--- a/source/blender/blenkernel/BKE_action.h
+++ b/source/blender/blenkernel/BKE_action.h
@@ -134,13 +134,16 @@ void action_groups_clear_tempflags(struct bAction *act);
 /* Pose API ----------------- */	
 
 void                 BKE_pose_channel_free(struct bPoseChannel *pchan);
+void                 BKE_pose_channel_free_ex(struct bPoseChannel *pchan, bool do_id_user);
 
 void                 BKE_pose_channels_free(struct bPose *pose);
+void                 BKE_pose_channels_free_ex(struct bPose *pose, bool do_id_user);
 
 void                 BKE_pose_channels_hash_make(struct bPose *pose);
 void                 BKE_pose_channels_hash_free(struct bPose *pose);
 
 void                 BKE_pose_free(struct bPose *pose);
+void                 BKE_pose_free_ex(struct bPose *pose, bool do_id_user);
 void                 BKE_pose_copy_data(struct bPose **dst, struct bPose *src, const bool copy_constraints);
 void                 BKE_pose_channel_copy_data(struct bPoseChannel *pchan, const struct bPoseChannel *pchan_from);
 struct bPoseChannel *BKE_pose_channel_find_name(const struct bPose *pose, const char *name);
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index b8da500..f97bb91 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -74,6 +74,7 @@ struct ListBase *which_libbase(struct Main *mainlib, short type);
 int set_listbasepointers(struct Main *main, struct ListBase **lb);
 
 void BKE_libblock_free(struct ListBase *lb, void *idv);
+void BKE_libblock_free_ex(struct ListBase *lb, void *idv, bool do_id_user);
 void BKE_libblock_free_us(struct ListBase *lb, void *idv);
 void BKE_libblock_free_data(struct ID *id);
 void free_main(struct Main *mainvar);
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index e6e6d62..9499540 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -65,6 +65,7 @@ void BKE_object_free_curve_cache(struct Object *ob);
 void BKE_object_update_base_layer(struct Scene *scene, struct Object *ob);
 
 void BKE_object_free(struct Object *ob);
+void BKE_object_free_ex(struct Object *ob, bool do_id_user);
 void BKE_object_free_derived_caches(struct Object *ob);
 
 void BKE_object_modifier_hook_reset(struct Object *ob, struct HookModifierData *hmd);
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index c91fae2..4991f1c 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -714,10 +714,12 @@ void BKE_pose_channels_hash_free(bPose *pose)
  * Deallocates a pose channel.
  * Does not free the pose channel itself.
  */
-void BKE_pose_channel_free(bPoseChannel *pchan)
+void BKE_pose_channel_free_ex(bPoseChannel *pchan, bool do_id_user)
 {
 	if (pchan->custom) {
-		id_us_min(&pchan->custom->id);
+		if (do_id_user) {
+			id_us_min(&pchan->custom->id);
+		}
 		pchan->custom = NULL;
 	}
 
@@ -734,17 +736,22 @@ void BKE_pose_channel_free(bPoseChannel *pchan)
 	}
 }
 
+void BKE_pose_channel_free(bPoseChannel *pchan)
+{
+	BKE_pose_channel_free_ex(pchan, true);
+}
+
 /**
  * Removes and deallocates all channels from a pose.
  * Does not free the pose itself.
  */
-void BKE_pose_channels_free(bPose *pose) 
+void BKE_pose_channels_free_ex(bPose *pose, bool do_id_user)
 {
 	bPoseChannel *pchan;
 	
 	if (pose->chanbase.first) {
 		for (pchan = pose->chanbase.first; pchan; pchan = pchan->next)
-			BKE_pose_channel_free(pchan);
+			BKE_pose_channel_free_ex(pchan, do_id_user);
 		
 		BLI_freelistN(&pose->chanbase);
 	}
@@ -752,14 +759,19 @@ void BKE_pose_channels_free(bPose *pose)
 	BKE_pose_channels_hash_free(pose);
 }
 
+void BKE_pose_channels_free(bPose *pose)
+{
+	BKE_pose_channels_free_ex(pose, true);
+}
+
 /**
  * Removes and deallocates all data from a pose, and also frees the pose.
  */
-void BKE_pose_free(bPose *pose)
+void BKE_pose_free_ex(bPose *pose, bool do_id_user)
 {
 	if (pose) {
 		/* free pose-channels */
-		BKE_pose_channels_free(pose);
+		BKE_pose_channels_free_ex(pose, do_id_user);
 		
 		/* free pose-groups */
 		if (pose->agroups.first)
@@ -777,6 +789,11 @@ void BKE_pose_free(bPose *pose)
 	}
 }
 
+void BKE_pose_free(bPose *pose)
+{
+	BKE_pose_free_ex(pose, true);
+}
+
 static void copy_pose_channel_data(bPoseChannel *pchan, const bPoseChannel *chan)
 {
 	bConstraint *pcon, *con;
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 9b8d34e..95f1cce 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -867,7 +867,7 @@ void BKE_libblock_free_data(ID *id)
 }
 
 /* used in headerbuttons.c image.c mesh.c screen.c sound.c and library.c */
-void BKE_libblock_free(ListBase *lb, void *idv)
+void BKE_libblock_free_ex(ListBase *lb, void *idv, bool do_id_user)
 {
 	Main *bmain = G.main;  /* should eventually be an arg */
 	ID *id = idv;
@@ -884,7 +884,7 @@ void BKE_libblock_free(ListBase *lb, void *idv)
 			BKE_library_free((Library *)id);
 			break;
 		case ID_OB:
-			BKE_object_free((Object *)id);
+			BKE_object_free_ex((Object *)id, do_id_user);
 			break;
 		case ID_ME:
 			BKE_mesh_free((Mesh *)id, 1);
@@ -987,6 +987,11 @@ void BKE_libblock_free(ListBase *lb, void *idv)
 	MEM_freeN(id);
 }
 
+void BKE_libblock_free(ListBase *lb, void *idv)
+{
+	BKE_libblock_free_ex(lb, idv, true);
+}
+
 void BKE_libblock_free_us(ListBase *lb, void *idv)      /* test users */
 {
 	ID *id = idv;
@@ -1018,44 +1023,44 @@ void free_main(Main *mainvar)
 		
 		while ( (id = lb->first) ) {
 #if 1
-			BKE_libblock_free(lb, id);
+			BKE_libblock_free_ex(lb, id, false);
 #else
 			/* errors freeing ID's can be hard to track down,
 			 * enable this so valgrind will give the line number in its error log */
 			switch (a) {
-				case   0: BKE_libblock_free(lb, id); break;
-				case   1: BKE_libblock_free(lb, id); break;
-				case   2: BKE_libblock_free(lb, id); break;
-				case   3: BKE_libblock_free(lb, id); break;
-				case   4: BKE_libblock_free(lb, id); break;
-				case   5: BKE_libblock_free(lb, id); break;
-				case   6: BKE_libblock_free(lb, id); break;
-				case   7: BKE_libblock_free(lb, id); break;
-				case   8: BKE_libblock_free(lb, id); break;
-				case   9: BKE_libblock_free(lb, id); break;
-				case  10: BKE_libblock_free(lb, id); break;
-				case  11: BKE_libblock_free(lb, id); break;
-				case  12: BKE_libblock_free(lb, id); break;
-				case  13: BKE_libblock_free(lb, id); break;
-				case  14: BKE_libblock_free(lb, id); break;
-				case  15: BKE_libblock_free(lb, id); break;
-				case  16: BKE_libblock_free(lb, id); break;
-				case  17: BKE_libblock_free(lb, id); break;
-				case  18: BKE_libblock_free(lb, id); break;
-				case  19: BKE_libblock_free(lb, id); break;
-				case  20: BKE_libblock_free(lb, id); break;
-				case  21: BKE_libblock_free(lb, id); break;
-				case  22: BKE_libblock_free(lb, id); break;
-				case  23: BKE_libblock_free(lb, id); break;
-				case  24: BKE_libblock_free(lb, id); break;
-				case  25: BKE_libblock_free(lb, id); break;
-				case  26: BKE_libblock_free(lb, id); break;
-				case  27: BKE_libblock_free(lb, id); break;
-				case  28: BKE_libblock_free(lb, id); break;
-				case  29: BKE_libblock_free(lb, id); break;
-				case  30: BKE_libblock_free(lb, id); break;
-				case  31: BKE_libblock_free(lb, id); break;
-				case  32: BKE_libblock_free(lb, id); break;
+				case   0: BKE_libblock_free_ex(lb, id, false); break;
+				case   1: BKE_libblock_free_ex(lb, id, false); break;
+				case   2: BKE_libblock_free_ex(lb, id, false); break;
+				case   3: BKE_libblock_free_ex(lb, id, false); break;
+				case   4: BKE_libblock_free_ex(lb, id, false); break;
+				case   5: BKE_libblock_free_ex(lb, id, false); break;
+				case   6: BKE_libblock_free_ex(lb, id, false); break;
+				case   7: BKE_libblock_free_ex(lb, id, false); break;
+				case   8: BKE_libblock_free_ex(lb, id, false); break;
+				case   9: BKE_libblock_free_ex(lb, id, false); break;
+				case  10: BKE_libblock_free_ex(lb, id, false); break;
+				case  11: BKE_libblock_free_ex(lb, id, false); break;
+				case  12: BKE_libblock_free_ex(lb, id, false); break;
+				case  13: BKE_libblock_free_ex(lb, id, false); break;
+				case  14: BKE_libblock_free_ex(lb, id, false); break;
+				case  15: BKE_libblock_free_ex(lb, id, false); break;
+				case  16: BKE_libblock_free_ex(lb, id, false); break;
+				case  17: BKE_libblock_free_ex(lb, id, false); break;
+				case  18: BKE_libblock_free_ex(lb, id, false); break;
+				case  19: BKE_libblock_free_ex(lb, id, false); break;
+				case  20: BKE_libblock_free_ex(lb, id, false); break;
+				case  21: BKE_libblock_free_ex(lb, id, false); break;
+				case  22: BKE_libblock_free_ex(lb, id, false); break;
+				case  23: BKE_libblock_free_ex(lb, id, false); break;
+				case  24: BKE_libblock_free_ex(lb, id, false); break;
+				case  25: BKE_libblock_free_ex(lb, id, false); break;
+				case  26: BKE_libblock_free_ex(lb, id, false); break;
+				case  27: BKE_libblock_free_ex(lb, id, false); break;
+				case  28: BKE_libblock_free_ex(lb, id, false); break;
+				case  29: BKE_libblock_free_ex(lb, id, false); break;
+				case  30: BKE_libblock_free_ex(lb, id, false); break;
+				case  31: BKE_libblock_free_ex(lb, id, false); break;
+				case  32: BKE_libblock_free_ex(lb, id, false); break;
 				default:
 					BLI_assert(0);
 					break;
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 8657e3b..e480f1a 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -321,7 +321,7 @@ void BKE_object_free_derived_caches(Object *ob)
 }
 
 /* do not free object itself */
-void BKE_object_free(Object *ob)
+void BKE_object_free_ex(Object *ob, bool do_id_user)
 {
 	int a;
 	
@@ -364,7 +364,7 @@ void BKE_object_free(Object *ob)
 	if (ob->defbase.first)
 		BLI_freelistN(&ob->defbase);
 	if (ob->pose)
-		BKE_pose_free(ob->pose);
+		BKE_pose_

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list