From 2e8b2558b4b86b97dafec539792d14b66b2724d1 Mon Sep 17 00:00:00 2001
From: "Graham Madarasz (Graham)" <graham@lindenlab.com>
Date: Thu, 7 Mar 2013 14:13:14 -0800
Subject: For MAINT-2436 and MAINT-2388 contribs from STORM-1935 and STORM-1936

---
 doc/contributions.txt                   |   2 +
 indra/llprimitive/llmodel.cpp           | 114 +++++++++++++++++++++++++++++++-
 indra/newview/llfloatermodelpreview.cpp |  42 +++++-------
 3 files changed, 133 insertions(+), 25 deletions(-)

diff --git a/doc/contributions.txt b/doc/contributions.txt
index 33b2ded81d..8611331722 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -899,6 +899,8 @@ NickyD
 Nicky Dasmijn
 	VWR-29228
 	MAINT-873
+	STORM-1935
+	STORM-1936
 Nicky Perian
 	OPEN-1
 	STORM-1087
diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp
index 8f0120b064..4ef4744981 100644
--- a/indra/llprimitive/llmodel.cpp
+++ b/indra/llprimitive/llmodel.cpp
@@ -186,32 +186,78 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa
 	
 	LLVolumeFace::VertexMapData::PointMap point_map;
 	
-	for (U32 i = 0; i < idx.getCount(); i += idx_stride)
+	U32 index_count  = idx.getCount();
+	U32 vertex_count = pos_source  ? v.getCount()  : 0;
+	U32 tc_count     = tc_source   ? tc.getCount() : 0;
+	U32 norm_count   = norm_source ? n.getCount()  : 0;
+
+	for (U32 i = 0; i < index_count; i += idx_stride)
 	{
 		LLVolumeFace::VertexData cv;
 		if (pos_source)
 		{
+			// guard against model data specifiying out of range indices or verts
+			//
+			if (((i + pos_offset) > index_count)
+			 || ((idx[i+pos_offset]*3+2) > vertex_count))
+			{
+				return LLModel::BAD_ELEMENT;
+			}
+
 			cv.setPosition(LLVector4a(v[idx[i+pos_offset]*3+0],
 								v[idx[i+pos_offset]*3+1],
 								v[idx[i+pos_offset]*3+2]));
 
 			if (!cv.getPosition().isFinite3())
+			{
 				return LLModel::BAD_ELEMENT;
+			}
 		}
 
 		if (tc_source)
 		{
+			// guard against model data specifiying out of range indices or tcs
+			//
+			if (((i + tc_offset) > index_count)
+			 || ((idx[i+pos_offset]*2+1) > tc_count))
+			{
+				return LLModel::BAD_ELEMENT;
+			}
+
 			cv.mTexCoord.setVec(tc[idx[i+tc_offset]*2+0],
 								tc[idx[i+tc_offset]*2+1]);
+
+			if (!cv.mTexCoord.isFinite())
+			{
+				llwarns << "Found NaN while loading tex coords from DAE-Model, invalid model." << llendl;
+				return LLModel::BAD_ELEMENT;
+			}
 		}
 		
 		if (norm_source)
 		{
+			// guard against model data specifiying out of range indices or norms
+			//
+			if (((i + pos_offset) > index_count)
+				|| ((idx[i+pos_offset]*3+2) > vertex_count))
+			{
+				return LLModel::BAD_ELEMENT;
+			}
+			if (((i + norm_offset) > index_count)
+				|| ((idx[i+norm_offset]*3+2) > norm_count))
+			{
+				return LLModel::BAD_ELEMENT;
+			}
+
 			cv.setNormal(LLVector4a(n[idx[i+norm_offset]*3+0],
 								n[idx[i+norm_offset]*3+1],
 								n[idx[i+norm_offset]*3+2]));
+
 			if (!cv.getNormal().isFinite3())
+			{
+				llwarns << "Found NaN while loading normals from DAE-Model, invalid model." << llendl;
 				return LLModel::BAD_ELEMENT;
+			}
 		}
 		
 		BOOL found = FALSE;
@@ -369,6 +415,11 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
 	
 	LLVolumeFace::VertexMapData::PointMap point_map;
 
+	U32 index_count  = idx.getCount();
+	U32 vertex_count = pos_source  ? v.getCount()  : 0;
+	U32 tc_count     = tc_source   ? tc.getCount() : 0;
+	U32 norm_count   = norm_source ? n.getCount()  : 0;
+
 	U32 cur_idx = 0;
 	for (U32 i = 0; i < vcount.getCount(); ++i)
 	{ //for each polygon
@@ -381,22 +432,65 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
 
 			if (pos_source)
 			{
+				// guard against model data specifiying out of range indices or verts
+				//
+				if (((i + pos_offset) > index_count)
+				 || ((idx[i+pos_offset]*3+2) > vertex_count))
+				{
+					return LLModel::BAD_ELEMENT;
+				}
+
 				cv.getPosition().set(v[idx[cur_idx+pos_offset]*3+0],
 									v[idx[cur_idx+pos_offset]*3+1],
 									v[idx[cur_idx+pos_offset]*3+2]);
+
+				if (!cv.getPosition().isFinite3())
+				{
+					llwarns << "Found NaN while loading positions from DAE-Model, invalid model." << llendl;
+					return LLModel::BAD_ELEMENT;
+				}
+
 			}
 
 			if (tc_source)
 			{
+				// guard against model data specifiying out of range indices or tcs
+				//
+				if (((i + pos_offset) > index_count)
+				 || ((idx[cur_idx+tc_offset]*2+1) > tc_count))
+				{
+					return LLModel::BAD_ELEMENT;
+				}
+
 				cv.mTexCoord.setVec(tc[idx[cur_idx+tc_offset]*2+0],
 									tc[idx[cur_idx+tc_offset]*2+1]);
+
+				if (!cv.mTexCoord.isFinite())
+				{
+					llwarns << "Found NaN while loading tex coords from DAE-Model, invalid model." << llendl;
+					return LLModel::BAD_ELEMENT;
+				}
 			}
 			
 			if (norm_source)
 			{
+				// guard against model data specifiying out of range indices or norms
+				//
+				if (((i + pos_offset) > index_count)
+				 || ((idx[cur_idx+norm_offset]*3+2) > norm_count))
+				{
+					return LLModel::BAD_ELEMENT;
+				}
+
 				cv.getNormal().set(n[idx[cur_idx+norm_offset]*3+0],
 									n[idx[cur_idx+norm_offset]*3+1],
 									n[idx[cur_idx+norm_offset]*3+2]);
+
+				if (!cv.getNormal().isFinite3())
+				{
+					llwarns << "Found NaN while loading normals from DAE-Model, invalid model." << llendl;
+					return LLModel::BAD_ELEMENT;
+				}
 			}
 			
 			cur_idx += idx_stride;
@@ -637,6 +731,12 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
 				vert.getPosition().set(v->get(v_idx),
 								v->get(v_idx+1),
 								v->get(v_idx+2));
+
+				if (!vert.getPosition().isFinite3())
+				{
+					llwarns << "Found NaN while loading position data from DAE-Model, invalid model." << llendl;
+					return LLModel::BAD_ELEMENT;
+				}
 			}
 			
 			//bounds check n and t lookups because some FBX to DAE converters
@@ -649,6 +749,12 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
 				vert.getNormal().set(n->get(n_idx),
 								n->get(n_idx+1),
 								n->get(n_idx+2));
+
+				if (!vert.getNormal().isFinite3())
+				{
+					llwarns << "Found NaN while loading normals from DAE-Model, invalid model." << llendl;
+					return LLModel::BAD_ELEMENT;
+				}
 			}
 			else
 			{
@@ -662,6 +768,12 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
 				t_idx = llclamp(t_idx, (U32) 0, (U32) t->getCount());
 				vert.mTexCoord.setVec(t->get(t_idx),
 								t->get(t_idx+1));								
+
+				if (!vert.mTexCoord.isFinite())
+				{
+					llwarns << "Found NaN while loading tex coords from DAE-Model, invalid model." << llendl;
+					return LLModel::BAD_ELEMENT;
+				}
 			}
 			else
 			{
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index 8ea0b43b36..07c36b9f1b 100755
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -290,6 +290,22 @@ bool ll_is_degenerate(const LLVector4a& a, const LLVector4a& b, const LLVector4a
 
 bool validate_face(const LLVolumeFace& face)
 {
+
+	for (U32 v = 0; v < face.mNumVertices; v++)
+	{
+		if(face.mPositions && !face.mPositions[v].isFinite3())
+		{
+			llwarns << "NaN position data in face found!" << llendl;
+			return false;
+		}
+
+		if(face.mNormals && !face.mNormals[v].isFinite3())
+		{
+			llwarns << "NaN normal data in face found!" << llendl;
+			return false;
+		}
+	}
+
 	for (U32 i = 0; i < face.mNumIndices; ++i)
 	{
 		if (face.mIndices[i] >= face.mNumVertices)
@@ -305,30 +321,6 @@ bool validate_face(const LLVolumeFace& face)
 		return false;
 	}
 
-	for (U32 i = 0; i < face.mNumIndices; i+=3)
-	{
-		U16 idx1 = face.mIndices[i];
-		U16 idx2 = face.mIndices[i+1];
-		U16 idx3 = face.mIndices[i+2];
-
-		if (face.mPositions
-		&& (!face.mPositions[idx1].isFinite3()
-		 || !face.mPositions[idx2].isFinite3()
-		 || !face.mPositions[idx3].isFinite3()))
-		{
-			llwarns << "NaN position data in face found!" << llendl;
-			return false;
-		}
-
-		if (face.mNormals
-		&& (!face.mNormals[idx1].isFinite3()
-		 || !face.mNormals[idx2].isFinite3()
-		 || !face.mNormals[idx3].isFinite3()))
-		{
-			llwarns << "NaN normal data in face found!" << llendl;
-			return false;
-		}
-	}
 
 	/*const LLVector4a scale(0.5f);
 
@@ -5959,3 +5951,5 @@ void LLFloaterModelPreview::setPermissonsErrorStatus(U32 status, const std::stri
 
 	LLNotificationsUtil::add("MeshUploadPermError");
 }
+
+
-- 
cgit v1.2.3