[Bf-blender-cvs] [b1ee10aa1ba] master: Fix T54073: crash and uninitialized memory in Cycles displacement hashing.

Brecht Van Lommel noreply at git.blender.org
Thu Feb 15 18:03:30 CET 2018


Commit: b1ee10aa1ba2d955b62142450830ecf748febd63
Author: Brecht Van Lommel
Date:   Thu Feb 15 15:28:34 2018 +0100
Branches: master
https://developer.blender.org/rBb1ee10aa1ba2d955b62142450830ecf748febd63

Fix T54073: crash and uninitialized memory in Cycles displacement hashing.

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

M	intern/cycles/graph/node.cpp

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

diff --git a/intern/cycles/graph/node.cpp b/intern/cycles/graph/node.cpp
index c71221746ad..19ed192652d 100644
--- a/intern/cycles/graph/node.cpp
+++ b/intern/cycles/graph/node.cpp
@@ -365,6 +365,14 @@ static bool is_array_equal(const Node *node, const Node *other, const SocketType
 	return *a == *b;
 }
 
+template<typename T>
+static bool is_value_equal(const Node *node, const Node *other, const SocketType& socket)
+{
+	const T *a = (const T*)(((char*)node) + socket.struct_offset);
+	const T *b = (const T*)(((char*)other) + socket.struct_offset);
+	return *a == *b;
+}
+
 bool Node::equals_value(const Node& other, const SocketType& socket) const
 {
 	if(socket.is_array()) {
@@ -384,9 +392,23 @@ bool Node::equals_value(const Node& other, const SocketType& socket) const
 		}
 	}
 	else {
-		const void *a = ((char*)this) + socket.struct_offset;
-		const void *b = ((char*)&other) + socket.struct_offset;
-		return (memcmp(a, b, socket.size()) == 0);
+		switch(socket.type) {
+			case SocketType::BOOLEAN: return is_value_equal<bool>(this, &other, socket);
+			case SocketType::FLOAT: return is_value_equal<float>(this, &other, socket);
+			case SocketType::INT: return is_value_equal<int>(this, &other, socket);
+			case SocketType::UINT: return is_value_equal<uint>(this, &other, socket);
+			case SocketType::COLOR: return is_value_equal<float3>(this, &other, socket);
+			case SocketType::VECTOR: return is_value_equal<float3>(this, &other, socket);
+			case SocketType::POINT: return is_value_equal<float3>(this, &other, socket);
+			case SocketType::NORMAL: return is_value_equal<float3>(this, &other, socket);
+			case SocketType::POINT2: return is_value_equal<float2>(this, &other, socket);
+			case SocketType::CLOSURE: return true;
+			case SocketType::STRING: return is_value_equal<ustring>(this, &other, socket);
+			case SocketType::ENUM: return is_value_equal<int>(this, &other, socket);
+			case SocketType::TRANSFORM: return is_value_equal<Transform>(this, &other, socket);
+			case SocketType::NODE: return is_value_equal<void*>(this, &other, socket);
+			default: assert(0); return true;
+		}
 	}
 }
 
@@ -406,6 +428,36 @@ bool Node::equals(const Node& other) const
 
 /* Hash */
 
+template<typename T>
+static void value_hash(const Node *node, const SocketType& socket, MD5Hash& md5)
+{
+	md5.append(((uint8_t*)node) + socket.struct_offset, socket.size());
+}
+
+static void float3_hash(const Node *node, const SocketType& socket, MD5Hash& md5)
+{
+	/* Don't compare 4th element used for padding. */
+	md5.append(((uint8_t*)node) + socket.struct_offset, sizeof(float) * 3);
+}
+
+template<typename T>
+static void array_hash(const Node *node, const SocketType& socket, MD5Hash& md5)
+{
+	const array<T>& a = *(const array<T>*)(((char*)node) + socket.struct_offset);
+	for (size_t i = 0; i < a.size(); i++) {
+		md5.append((uint8_t*)&a[i], sizeof(T));
+	}
+}
+
+static void float3_array_hash(const Node *node, const SocketType& socket, MD5Hash& md5)
+{
+	/* Don't compare 4th element used for padding. */
+	const array<float3>& a = *(const array<float3>*)(((char*)node) + socket.struct_offset);
+	for (size_t i = 0; i < a.size(); i++) {
+		md5.append((uint8_t*)&a[i], sizeof(float) * 3);
+	}
+}
+
 void Node::hash(MD5Hash& md5)
 {
 	md5.append(type->name.string());
@@ -414,11 +466,39 @@ void Node::hash(MD5Hash& md5)
 		md5.append(socket.name.string());
 
 		if(socket.is_array()) {
-			const array<bool>* a = (const array<bool>*)(((char*)this) + socket.struct_offset);
-			md5.append((uint8_t*)a->data(), socket.size() * a->size());
+			switch(socket.type) {
+				case SocketType::BOOLEAN_ARRAY: array_hash<bool>(this, socket, md5); break;
+				case SocketType::FLOAT_ARRAY: array_hash<float>(this, socket, md5); break;
+				case SocketType::INT_ARRAY: array_hash<int>(this, socket, md5); break;
+				case SocketType::COLOR_ARRAY: float3_array_hash(this, socket, md5); break;
+				case SocketType::VECTOR_ARRAY: float3_array_hash(this, socket, md5); break;
+				case SocketType::POINT_ARRAY: float3_array_hash(this, socket, md5); break;
+				case SocketType::NORMAL_ARRAY: float3_array_hash(this, socket, md5); break;
+				case SocketType::POINT2_ARRAY: array_hash<float2>(this, socket, md5); break;
+				case SocketType::STRING_ARRAY: array_hash<ustring>(this, socket, md5); break;
+				case SocketType::TRANSFORM_ARRAY: array_hash<Transform>(this, socket, md5); break;
+				case SocketType::NODE_ARRAY: array_hash<void*>(this, socket, md5); break;
+				default: assert(0); break;
+			}
 		}
 		else {
-			md5.append(((uint8_t*)this) + socket.struct_offset, socket.size());
+			switch(socket.type) {
+				case SocketType::BOOLEAN: value_hash<bool>(this, socket, md5); break;
+				case SocketType::FLOAT: value_hash<float>(this, socket, md5); break;
+				case SocketType::INT: value_hash<int>(this, socket, md5); break;
+				case SocketType::UINT: value_hash<uint>(this, socket, md5); break;
+				case SocketType::COLOR: float3_hash(this, socket, md5); break;
+				case SocketType::VECTOR: float3_hash(this, socket, md5); break;
+				case SocketType::POINT: float3_hash(this, socket, md5); break;
+				case SocketType::NORMAL: float3_hash(this, socket, md5); break;
+				case SocketType::POINT2: value_hash<float2>(this, socket, md5); break;
+				case SocketType::CLOSURE: break;
+				case SocketType::STRING: value_hash<ustring>(this, socket, md5); break;
+				case SocketType::ENUM: value_hash<int>(this, socket, md5); break;
+				case SocketType::TRANSFORM: value_hash<Transform>(this, socket, md5); break;
+				case SocketType::NODE: value_hash<void*>(this, socket, md5); break;
+				default: assert(0); break;
+			}
 		}
 	}
 }



More information about the Bf-blender-cvs mailing list