[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [51809] trunk/blender/source/blender: fix for long standing problem with blender 2.5x py api.

Campbell Barton ideasman42 at gmail.com
Thu Nov 1 16:56:43 CET 2012


Revision: 51809
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=51809
Author:   campbellbarton
Date:     2012-11-01 15:56:42 +0000 (Thu, 01 Nov 2012)
Log Message:
-----------
fix for long standing problem with blender 2.5x py api.
Removing data then accessing would allow invalid memory access and often crash.

Example:
  import bpy
  image = bpy.data.images.new(name="a", width=5, height=5)
  bpy.data.images.remove(image)
  print(image.name)

Now access to the removed data raises an error:
  ReferenceError: StructRNA of type Image has been removed

This is the same level of error checking that was done in blender 2.4x but was made difficult by RNA functions not having access to the PyObject's.

Modified Paths:
--------------
    trunk/blender/source/blender/makesrna/RNA_access.h
    trunk/blender/source/blender/makesrna/intern/makesrna.c
    trunk/blender/source/blender/makesrna/intern/rna_define.c
    trunk/blender/source/blender/makesrna/intern/rna_main_api.c
    trunk/blender/source/blender/python/intern/bpy_rna.c

Modified: trunk/blender/source/blender/makesrna/RNA_access.h
===================================================================
--- trunk/blender/source/blender/makesrna/RNA_access.h	2012-11-01 15:51:24 UTC (rev 51808)
+++ trunk/blender/source/blender/makesrna/RNA_access.h	2012-11-01 15:56:42 UTC (rev 51809)
@@ -1032,6 +1032,13 @@
 StructRNA *ID_code_to_RNA_type(short idcode);
 
 
+#define RNA_POINTER_INVALIDATE(ptr) {                                         \
+	/* this is checked for validity */                                        \
+	(ptr)->type =                                                             \
+	/* should not be needed but prevent bad pointer access, just in case */   \
+	(ptr)->id.data = NULL;                                                    \
+} (void)0
+
 /* macro which inserts the function name */
 #if defined __GNUC__ || defined __sun
 #  define RNA_warning(format, args ...) _RNA_warning("%s: " format "\n", __func__, ##args)

Modified: trunk/blender/source/blender/makesrna/intern/makesrna.c
===================================================================
--- trunk/blender/source/blender/makesrna/intern/makesrna.c	2012-11-01 15:51:24 UTC (rev 51808)
+++ trunk/blender/source/blender/makesrna/intern/makesrna.c	2012-11-01 15:56:42 UTC (rev 51809)
@@ -2095,6 +2095,8 @@
 		/* fixed size arrays and RNA pointers are pre-allocated on the ParameterList stack, pass a pointer to it */
 		else if (type == PROP_POINTER || dparm->prop->arraydimension)
 			ptrstr = "*";
+		else if ((type == PROP_POINTER) && (flag & PROP_RNAPTR) && !(flag & PROP_THICK_WRAP))
+			ptrstr = "*";
 		/* PROP_THICK_WRAP strings are pre-allocated on the ParameterList stack,
 		 * but type name for string props is already char*, so leave empty */
 		else if (type == PROP_STRING && (flag & PROP_THICK_WRAP))
@@ -2146,6 +2148,10 @@
 				ptrstr = "**";
 				valstr = "*";
 			}
+			else if ((type == PROP_POINTER) && !(flag & PROP_THICK_WRAP)) {
+				ptrstr = "**";
+				valstr = "*";
+			}
 			else if (type == PROP_POINTER || dparm->prop->arraydimension) {
 				ptrstr = "*";
 				valstr = "";

Modified: trunk/blender/source/blender/makesrna/intern/rna_define.c
===================================================================
--- trunk/blender/source/blender/makesrna/intern/rna_define.c	2012-11-01 15:51:24 UTC (rev 51808)
+++ trunk/blender/source/blender/makesrna/intern/rna_define.c	2012-11-01 15:56:42 UTC (rev 51809)
@@ -981,8 +981,10 @@
 			sprop->defaultvalue = "";
 			break;
 		}
+		case PROP_POINTER:
+			prop->flag |= PROP_THICK_WRAP;  /* needed for default behavior when PROP_RNAPTR is set */
+			break;
 		case PROP_ENUM:
-		case PROP_POINTER:
 		case PROP_COLLECTION:
 			break;
 		default:
@@ -2810,14 +2812,26 @@
 			{
 #ifdef RNA_RUNTIME
 				if (parm->flag & PROP_RNAPTR)
-					return sizeof(PointerRNA);
+					if (parm->flag & PROP_THICK_WRAP) {
+						return sizeof(PointerRNA);
+					}
+					else {
+						return sizeof(PointerRNA *);
+					}
 				else
 					return sizeof(void *);
 #else
-				if (parm->flag & PROP_RNAPTR)
-					return sizeof(PointerRNA);
-				else
+				if (parm->flag & PROP_RNAPTR) {
+					if (parm->flag & PROP_THICK_WRAP) {
+						return sizeof(PointerRNA);
+					}
+					else {
+						return sizeof(PointerRNA *);
+					}
+				}
+				else {
 					return sizeof(void *);
+				}
 #endif
 			}
 			case PROP_COLLECTION:

Modified: trunk/blender/source/blender/makesrna/intern/rna_main_api.c
===================================================================
--- trunk/blender/source/blender/makesrna/intern/rna_main_api.c	2012-11-01 15:51:24 UTC (rev 51808)
+++ trunk/blender/source/blender/makesrna/intern/rna_main_api.c	2012-11-01 15:56:42 UTC (rev 51809)
@@ -296,15 +296,17 @@
 
 	return ima;
 }
-static void rna_Main_images_remove(Main *bmain, ReportList *reports, Image *image)
+static void rna_Main_images_remove(Main *bmain, ReportList *reports, struct PointerRNA *image_ptr)
 {
-	if (ID_REAL_USERS(image) <= 0)
+	Image *image = image_ptr->data;
+	if (ID_REAL_USERS(image) <= 0) {
 		BKE_libblock_free(&bmain->image, image);
-	else
+		RNA_POINTER_INVALIDATE(image_ptr);
+	}
+	else {
 		BKE_reportf(reports, RPT_ERROR, "Image '%s' must have zero users to be removed, found %d",
 		            image->id.name + 2, ID_REAL_USERS(image));
-
-	/* XXX python now has invalid pointer? */
+	}
 }
 
 static Lattice *rna_Main_lattices_new(Main *UNUSED(bmain), const char *name)
@@ -1015,7 +1017,8 @@
 	RNA_def_function_flag(func, FUNC_USE_REPORTS);
 	RNA_def_function_ui_description(func, "Remove an image from the current blendfile");
 	parm = RNA_def_pointer(func, "image", "Image", "", "Image to remove");
-	RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+	RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
+	RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);  /* pass the pointer direct */
 
 	func = RNA_def_function(srna, "tag", "rna_Main_images_tag");
 	parm = RNA_def_boolean(func, "value", 0, "Value", "");

Modified: trunk/blender/source/blender/python/intern/bpy_rna.c
===================================================================
--- trunk/blender/source/blender/python/intern/bpy_rna.c	2012-11-01 15:51:24 UTC (rev 51808)
+++ trunk/blender/source/blender/python/intern/bpy_rna.c	2012-11-01 15:56:42 UTC (rev 51809)
@@ -121,8 +121,7 @@
 
 void pyrna_invalidate(BPy_DummyPointerRNA *self)
 {
-	self->ptr.type = NULL; /* this is checked for validity */
-	self->ptr.id.data = NULL; /* should not be needed but prevent bad pointer access, just in case */
+	RNA_POINTER_INVALIDATE(&self->ptr);
 }
 
 #ifdef USE_PYRNA_INVALIDATE_GC
@@ -1776,10 +1775,21 @@
 					if (data) {
 
 						if (flag & PROP_RNAPTR) {
-							if (value == Py_None)
-								memset(data, 0, sizeof(PointerRNA));
-							else
-								*((PointerRNA *)data) = param->ptr;
+							if (flag & PROP_THICK_WRAP) {
+								if (value == Py_None)
+									memset(data, 0, sizeof(PointerRNA));
+								else
+									*((PointerRNA *)data) = param->ptr;
+							}
+							else {
+								/* for function calls, we sometimes want to pass the 'ptr' directly,
+								 * watch out that it remains valid!, possibly we could support this later if needed */
+								BLI_assert(value_new == NULL);
+								if (value == Py_None)
+									*((void **)data) = NULL;
+								else
+									*((PointerRNA **)data) = &param->ptr;
+							}
 						}
 						else if (value == Py_None) {
 							*((void **)data) = NULL;




More information about the Bf-blender-cvs mailing list