Sfoglia il codice sorgente

Added a check that makes sure RTTI plain fields are POD, so we don't cause data corruption by accidentially memcpying something that can't be memcpyed properly

Marko Pintera 13 anni fa
parent
commit
d220a6bf24

+ 0 - 3
CamelotClient/CamelotClient.cpp

@@ -1,6 +1,3 @@
-// CamelotClient.cpp : Defines the entry point for the console application.
-//
-
 #include "stdafx.h"
 #include "stdafx.h"
 #include <windows.h>
 #include <windows.h>
 
 

+ 2 - 0
CamelotRenderer/Include/CmDepthStencilState.h

@@ -44,6 +44,8 @@ namespace CamelotEngine
 		CompareFunction backStencilComparisonFunc;
 		CompareFunction backStencilComparisonFunc;
 	};
 	};
 
 
+	CM_ALLOW_MEMCPY_SERIALIZATION(DEPTH_STENCIL_STATE_DESC);
+
 	// TODO Low priority - Write doc explaining various states
 	// TODO Low priority - Write doc explaining various states
 	class CM_EXPORT DepthStencilState : public Resource
 	class CM_EXPORT DepthStencilState : public Resource
 	{
 	{

+ 2 - 0
CamelotRenderer/Include/CmMeshDataRTTI.h

@@ -66,6 +66,8 @@ namespace CamelotEngine
 		}
 		}
 	};
 	};
 
 
+	CM_ALLOW_MEMCPY_SERIALIZATION(MeshData::SubMeshData);
+
 	class CM_EXPORT MeshDataRTTI : public RTTIType<MeshData, IReflectable, MeshDataRTTI>
 	class CM_EXPORT MeshDataRTTI : public RTTIType<MeshData, IReflectable, MeshDataRTTI>
 	{
 	{
 	private:
 	private:

+ 2 - 0
CamelotRenderer/Include/CmRasterizerStateRTTI.h

@@ -7,6 +7,8 @@
 
 
 namespace CamelotEngine
 namespace CamelotEngine
 {
 {
+	CM_ALLOW_MEMCPY_SERIALIZATION(RASTERIZER_STATE_DESC);
+
 	class CM_EXPORT RasterizerStateRTTI : public RTTIType<RasterizerState, IReflectable, RasterizerStateRTTI>
 	class CM_EXPORT RasterizerStateRTTI : public RTTIType<RasterizerState, IReflectable, RasterizerStateRTTI>
 	{
 	{
 	private:
 	private:

+ 2 - 0
CamelotRenderer/Include/CmSamplerStateRTTI.h

@@ -7,6 +7,8 @@
 
 
 namespace CamelotEngine
 namespace CamelotEngine
 {
 {
+	CM_ALLOW_MEMCPY_SERIALIZATION(SAMPLER_STATE_DESC);
+
 	class CM_EXPORT SamplerStateRTTI : public RTTIType<SamplerState, IReflectable, SamplerStateRTTI>
 	class CM_EXPORT SamplerStateRTTI : public RTTIType<SamplerState, IReflectable, SamplerStateRTTI>
 	{
 	{
 	private:
 	private:

+ 2 - 0
CamelotRenderer/Include/CmVertexDeclarationRTTI.h

@@ -7,6 +7,8 @@
 
 
 namespace CamelotEngine
 namespace CamelotEngine
 {
 {
+	CM_ALLOW_MEMCPY_SERIALIZATION(VertexElement);
+
 	class VertexDeclarationRTTI : public RTTIType<VertexDeclaration, IReflectable, VertexDeclarationRTTI>
 	class VertexDeclarationRTTI : public RTTIType<VertexDeclaration, IReflectable, VertexDeclarationRTTI>
 	{
 	{
 	private:
 	private:

+ 0 - 3
CamelotRenderer/TODO.txt

@@ -160,9 +160,6 @@ Low priority TODO:
  - D3D9Texture::createTextureResources is commented out at the moment. It gets called on device reset, and at that point I should reload texture resources.
  - D3D9Texture::createTextureResources is commented out at the moment. It gets called on device reset, and at that point I should reload texture resources.
   - I should probably keep all resources by DX managed. OpenGL apparently keeps a mirror of all its resources anyway.
   - I should probably keep all resources by DX managed. OpenGL apparently keeps a mirror of all its resources anyway.
  - Device reset and resource re-loading in general
  - Device reset and resource re-loading in general
- - In RTTIType it is possible to add a non-plain data type using addPlainField. This can cause memory corruption issues
-   if pointer is saved/loaded as a plain field. I need to add a check that ensures the type is POD. 
-   See: http://www.boost.org/doc/libs/1_51_0/boost/mpi/datatype.hpp for a possible implementation of a compile time check.
  - Fix up WorkQueue as it doesn't lock when initializing, to make sure threads are actually started before returning
  - Fix up WorkQueue as it doesn't lock when initializing, to make sure threads are actually started before returning
  - CPU reading or writing to a render texture in OpenGL is not supported. (CmGLHardwarePixelBuffer::upload/download). 
  - CPU reading or writing to a render texture in OpenGL is not supported. (CmGLHardwarePixelBuffer::upload/download). 
  - When saving a resource, make sure resource is properly loaded before saving
  - When saving a resource, make sure resource is properly loaded before saving

+ 1 - 0
CamelotUtility/CamelotUtility.vcxproj

@@ -193,6 +193,7 @@
     <ClInclude Include="Include\CmRTTIField.h" />
     <ClInclude Include="Include\CmRTTIField.h" />
     <ClInclude Include="Include\CmRTTIManagedDataBlockField.h" />
     <ClInclude Include="Include\CmRTTIManagedDataBlockField.h" />
     <ClInclude Include="Include\CmRTTIPlainField.h" />
     <ClInclude Include="Include\CmRTTIPlainField.h" />
+    <ClInclude Include="Include\CmRTTIPrerequisites.h" />
     <ClInclude Include="Include\CmRTTIReflectableField.h" />
     <ClInclude Include="Include\CmRTTIReflectableField.h" />
     <ClInclude Include="Include\CmRTTIReflectablePtrField.h" />
     <ClInclude Include="Include\CmRTTIReflectablePtrField.h" />
     <ClInclude Include="Include\CmRTTIType.h" />
     <ClInclude Include="Include\CmRTTIType.h" />

+ 3 - 0
CamelotUtility/CamelotUtility.vcxproj.filters

@@ -207,6 +207,9 @@
     <ClInclude Include="Include\CmUtil.h">
     <ClInclude Include="Include\CmUtil.h">
       <Filter>Header Files</Filter>
       <Filter>Header Files</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="Include\CmRTTIPrerequisites.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="Include\CmAxisAlignedBox.cpp">
     <ClCompile Include="Include\CmAxisAlignedBox.cpp">

+ 1 - 0
CamelotUtility/Include/CmColor.h

@@ -329,6 +329,7 @@ namespace CamelotEngine {
 	/** @} */
 	/** @} */
 	/** @} */
 	/** @} */
 
 
+	CM_ALLOW_MEMCPY_SERIALIZATION(Color);
 } // namespace
 } // namespace
 
 
 #endif
 #endif

+ 2 - 0
CamelotUtility/Include/CmMatrix3.h

@@ -268,5 +268,7 @@ namespace CamelotEngine
     };
     };
 	/** @} */
 	/** @} */
 	/** @} */
 	/** @} */
+
+	CM_ALLOW_MEMCPY_SERIALIZATION(Matrix3);
 }
 }
 #endif
 #endif

+ 1 - 0
CamelotUtility/Include/CmMatrix4.h

@@ -656,5 +656,6 @@ namespace CamelotEngine
 	/** @} */
 	/** @} */
 	/** @} */
 	/** @} */
 
 
+	CM_ALLOW_MEMCPY_SERIALIZATION(Matrix4);
 }
 }
 #endif
 #endif

+ 3 - 1
CamelotUtility/Include/CmPrerequisitesUtil.h

@@ -70,4 +70,6 @@ THE SOFTWARE
 // Forward declarations
 // Forward declarations
 #include "CmFwdDeclUtil.h"
 #include "CmFwdDeclUtil.h"
 
 
-#include "CmString.h"
+#include "CmString.h"
+
+#include "CmRTTIPrerequisites.h"

+ 1 - 96
CamelotUtility/Include/CmRTTIField.h

@@ -5,6 +5,7 @@
 #include <boost/function.hpp>
 #include <boost/function.hpp>
 #include <boost/any.hpp>
 #include <boost/any.hpp>
 #include <boost/static_assert.hpp>
 #include <boost/static_assert.hpp>
+#include <type_traits>
 
 
 #include "CmPrerequisitesUtil.h"
 #include "CmPrerequisitesUtil.h"
 #include "CmIReflectable.h"
 #include "CmIReflectable.h"
@@ -16,102 +17,6 @@ namespace CamelotEngine
 	class RTTITypeBase;
 	class RTTITypeBase;
 	struct RTTIField;
 	struct RTTIField;
 
 
-	/**
-	* @brief	Helper method when serializing known data types that have valid
-	* 			SerializableSimpleType specializations.
-	* 			
-	*			Returns the size of the element. If elements serializable type is 
-	*			specialized with hasDynamicSize == true, the dynamic size is calculated, 
-	*			otherwise sizeof() is used.
-	 */
-	template<class ElemType>
-	UINT32 rttiGetElemSize(ElemType& data)
-	{
-		if(SerializableSimpleType<ElemType>::hasDynamicSize == 1)
-			return SerializableSimpleType<ElemType>::getDynamicSize(data);
-		else
-			return sizeof(ElemType);
-	}
-
-	/**
-	 * @brief	Helper method when serializing known data types that have valid
-	 * 			SerializableSimpleType specializations.
-	 * 			
-	 *			Writes the specified data into memory, advances the memory pointer by the
-	 *			bytes written and returns pointer to new memory.
-	 */
-	template<class ElemType>
-	char* rttiWriteElem(ElemType& data, char* memory)
-	{
-		SerializableSimpleType<ElemType>::toMemory(data, memory);
-
-		return memory + rttiGetElemSize(data);
-	}
-
-	/**
-	 * @brief	Helper method when serializing known data types that have valid
-	 * 			SerializableSimpleType specializations.
-	 * 			
-	 *			Reads the specified data into memory, advances the memory pointer by the
-	 *			bytes read and returns pointer to new memory.
-	 */
-	template<class ElemType>
-	char* rttiReadElem(ElemType& data, char* memory)
-	{
-		SerializableSimpleType<ElemType>::fromMemory(data, memory);
-
-		return memory + rttiGetElemSize(data);
-	}
-
-	template<class T>
-	struct SerializableSimpleType 
-	{ 
-		//BOOST_STATIC_ASSERT_MSG(sizeof(T) == 0, // We need this hacky check, otherwise if we only use "false" compiler will evaluate the template and trigger this message 
-		//	"Provided data type isn't marked as serializable. Declare SerializableSimpleType template specialization to define a unique ID and needed methods for the type.");
-
-		enum { id = 0 }; 
-		enum { hasDynamicSize = 0 };
-
-		static void toMemory(T& data, char* memory)	
-		{ 
-			memcpy(memory, &data, sizeof(T)); 
-		}
-
-		static void fromMemory(T& data, char* memory)
-		{
-			memcpy(&data, memory, sizeof(T)); 
-		}
-
-		static UINT32 getDynamicSize(T& data)
-		{ 
-			assert(false); 
-			return sizeof(T);
-		}
-	};
-
-#define CM_SERIALIZABLE_SIMPLE_TYPE(type, type_id)				\
-	template<> struct SerializableSimpleType<##type##>			\
-	{	enum { id=##type_id }; enum { hasDynamicSize = 0 };		\
-	static void toMemory(##type##& data, char* memory)		\
-	{ memcpy(memory, &data, sizeof(##type##)); }			\
-	static void fromMemory(##type##& data, char* memory)	\
-	{ memcpy(&data, memory, sizeof(##type##)); }			\
-	static UINT32 getDynamicSize(##type##& data)			\
-	{ assert(false); return sizeof(##type##); }				\
-	}; 
-
-	CM_SERIALIZABLE_SIMPLE_TYPE(UINT8, 1);
-	CM_SERIALIZABLE_SIMPLE_TYPE(UINT16, 2);
-	CM_SERIALIZABLE_SIMPLE_TYPE(UINT32, 3);
-	CM_SERIALIZABLE_SIMPLE_TYPE(UINT64, 4);
-	CM_SERIALIZABLE_SIMPLE_TYPE(INT8, 5);
-	CM_SERIALIZABLE_SIMPLE_TYPE(INT16, 6);
-	CM_SERIALIZABLE_SIMPLE_TYPE(INT32, 7);
-	CM_SERIALIZABLE_SIMPLE_TYPE(INT64, 8);
-	CM_SERIALIZABLE_SIMPLE_TYPE(float, 9);
-	CM_SERIALIZABLE_SIMPLE_TYPE(double, 10);
-	CM_SERIALIZABLE_SIMPLE_TYPE(bool, 11);
-		
 	/**
 	/**
 	 * @brief	Strings need to copy their data in a slightly more intricate way than just memcpy.
 	 * @brief	Strings need to copy their data in a slightly more intricate way than just memcpy.
 	 */
 	 */

+ 89 - 0
CamelotUtility/Include/CmRTTIPrerequisites.h

@@ -0,0 +1,89 @@
+#pragma once
+
+namespace CamelotEngine
+{
+	/**
+	* @brief	Helper method when serializing known data types that have valid
+	* 			SerializableSimpleType specializations.
+	* 			
+	*			Returns the size of the element. If elements serializable type is 
+	*			specialized with hasDynamicSize == true, the dynamic size is calculated, 
+	*			otherwise sizeof() is used.
+	 */
+	template<class ElemType>
+	UINT32 rttiGetElemSize(ElemType& data)
+	{
+		if(SerializableSimpleType<ElemType>::hasDynamicSize == 1)
+			return SerializableSimpleType<ElemType>::getDynamicSize(data);
+		else
+			return sizeof(ElemType);
+	}
+
+	/**
+	 * @brief	Helper method when serializing known data types that have valid
+	 * 			SerializableSimpleType specializations.
+	 * 			
+	 *			Writes the specified data into memory, advances the memory pointer by the
+	 *			bytes written and returns pointer to new memory.
+	 */
+	template<class ElemType>
+	char* rttiWriteElem(ElemType& data, char* memory)
+	{
+		SerializableSimpleType<ElemType>::toMemory(data, memory);
+
+		return memory + rttiGetElemSize(data);
+	}
+
+	/**
+	 * @brief	Helper method when serializing known data types that have valid
+	 * 			SerializableSimpleType specializations.
+	 * 			
+	 *			Reads the specified data into memory, advances the memory pointer by the
+	 *			bytes read and returns pointer to new memory.
+	 */
+	template<class ElemType>
+	char* rttiReadElem(ElemType& data, char* memory)
+	{
+		SerializableSimpleType<ElemType>::fromMemory(data, memory);
+
+		return memory + rttiGetElemSize(data);
+	}
+
+	template<class T>
+	struct SerializableSimpleType 
+	{ 
+		static_assert(std::is_pod<T>::value, 
+			"Serializable type isn't plain-old-data. You need to specialize SerializableSimpleType template in order to serialize this type. "\
+			" (Or call CM_MAKE_SERIALIZABLE(type) macro if you are sure the type can be properly serialized using just memcpy.)");
+
+		enum { id = 0 }; 
+		enum { hasDynamicSize = 0 };
+
+		static void toMemory(T& data, char* memory)	
+		{ 
+			memcpy(memory, &data, sizeof(T)); 
+		}
+
+		static void fromMemory(T& data, char* memory)
+		{
+			memcpy(&data, memory, sizeof(T)); 
+		}
+
+		static UINT32 getDynamicSize(T& data)
+		{ 
+			assert(false); 
+			return sizeof(T);
+		}
+	};
+
+#define CM_ALLOW_MEMCPY_SERIALIZATION(type)				\
+	template<> struct SerializableSimpleType<##type##>			\
+	{	enum { id=0 }; enum { hasDynamicSize = 0 };		\
+	static void toMemory(##type##& data, char* memory)		\
+	{ memcpy(memory, &data, sizeof(##type##)); }			\
+	static void fromMemory(##type##& data, char* memory)	\
+	{ memcpy(&data, memory, sizeof(##type##)); }			\
+	static UINT32 getDynamicSize(##type##& data)			\
+	{ assert(false); return sizeof(##type##); }				\
+	}; 
+}

+ 1 - 1
CamelotUtility/Include/CmVector2.h

@@ -34,7 +34,6 @@ THE SOFTWARE.
 
 
 namespace CamelotEngine
 namespace CamelotEngine
 {
 {
-
 	/** \addtogroup Core
 	/** \addtogroup Core
 	*  @{
 	*  @{
 	*/
 	*/
@@ -569,5 +568,6 @@ namespace CamelotEngine
 	/** @} */
 	/** @} */
 	/** @} */
 	/** @} */
 
 
+	CM_ALLOW_MEMCPY_SERIALIZATION(Vector2);
 }
 }
 #endif
 #endif

+ 1 - 1
CamelotUtility/Include/CmVector3.h

@@ -34,7 +34,6 @@ THE SOFTWARE.
 
 
 namespace CamelotEngine
 namespace CamelotEngine
 {
 {
-
 	/** \addtogroup Core
 	/** \addtogroup Core
 	*  @{
 	*  @{
 	*/
 	*/
@@ -795,5 +794,6 @@ namespace CamelotEngine
 	/** @} */
 	/** @} */
 	/** @} */
 	/** @} */
 
 
+	CM_ALLOW_MEMCPY_SERIALIZATION(Vector3);
 }
 }
 #endif
 #endif

+ 1 - 1
CamelotUtility/Include/CmVector4.h

@@ -33,7 +33,6 @@ THE SOFTWARE.
 
 
 namespace CamelotEngine
 namespace CamelotEngine
 {
 {
-
 	/** \addtogroup Core
 	/** \addtogroup Core
 	*  @{
 	*  @{
 	*/
 	*/
@@ -409,6 +408,7 @@ namespace CamelotEngine
 	/** @} */
 	/** @} */
 	/** @} */
 	/** @} */
 
 
+	CM_ALLOW_MEMCPY_SERIALIZATION(Vector4);
 }
 }
 #endif
 #endif