From cb8641a639d077fe03853e69be597ee359f5a01f Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Sat, 27 Jun 2009 01:05:56 +0000
Subject: [PATCH] fix for DEV-27483/SEC-283: Viewer crash: LLXform::setParent
 Creating loop when setting parent

---
 indra/llmath/xform.h             |  2 +-
 indra/newview/llviewerobject.cpp | 45 ++++++++++++++++++--------------
 indra/newview/llviewerobject.h   |  2 +-
 indra/newview/llvoavatar.cpp     | 13 ++++++---
 indra/newview/llvoavatar.h       |  2 +-
 indra/newview/llvovolume.cpp     |  9 ++++---
 indra/newview/llvovolume.h       |  2 +-
 7 files changed, 45 insertions(+), 30 deletions(-)

diff --git a/indra/llmath/xform.h b/indra/llmath/xform.h
index d3be28f41d8..5b7b1900bcb 100644
--- a/indra/llmath/xform.h
+++ b/indra/llmath/xform.h
@@ -173,7 +173,7 @@ BOOL LLXform::setParent(LLXform* parent)
 		{
 			if (cur_par == this)
 			{
-				llwarns << "LLXform::setParent Creating loop when setting parent!" << llendl;
+				//llwarns << "LLXform::setParent Creating loop when setting parent!" << llendl;
 				return FALSE;
 			}
 			cur_par = cur_par->mParent;
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index dc4f2b2990e..a96ccfd8489 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -512,15 +512,24 @@ BOOL LLViewerObject::isOverGroupOwnedLand() const
 		&& mRegionp->getParcelOverlay()->isOwnedGroup(getPositionRegion());
 }
 
-void LLViewerObject::setParent(LLViewerObject* parent)
+BOOL LLViewerObject::setParent(LLViewerObject* parent)
 {
-	LLPrimitive::setParent(parent);
+	if(mParent != parent)
+	{
+		LLViewerObject* old_parent = (LLViewerObject*)mParent ;		
+		BOOL ret = LLPrimitive::setParent(parent);
+		if(ret && old_parent && parent)
+		{
+			old_parent->removeChild(this) ;
+		}
+		return ret ;
+	}
+
+	return FALSE ;
 }
 
 void LLViewerObject::addChild(LLViewerObject *childp)
 {
-	BOOL result = TRUE;
-	
 	for (child_list_t::iterator i = mChildList.begin(); i != mChildList.end(); ++i)
 	{
 		if (*i == childp)
@@ -535,18 +544,9 @@ void LLViewerObject::addChild(LLViewerObject *childp)
 		childp->mbCanSelect = mbCanSelect;
 	}
 
-	childp->setParent(this);
-	mChildList.push_back(childp);
-
-	if (!result) 
+	if(childp->setParent(this))
 	{
-		llwarns << "Failed to attach child " << childp->getID() << " to object " << getID() << llendl;
-		removeChild(childp);
-		if (mJointInfo)
-		{
-			delete mJointInfo;
-			mJointInfo = NULL;
-		}
+		mChildList.push_back(childp);
 	}
 }
 
@@ -562,7 +562,11 @@ void LLViewerObject::removeChild(LLViewerObject *childp)
 			}
 
 			mChildList.erase(i);
-			childp->setParent(NULL);			
+
+			if(childp->getParent() == this)
+			{
+				childp->setParent(NULL);			
+			}
 			break;
 		}
 	}
@@ -644,11 +648,14 @@ BOOL LLViewerObject::setDrawableParent(LLDrawable* parentp)
 		return FALSE;
 	}
 
+	BOOL ret = mDrawable->mXform.setParent(parentp ? &parentp->mXform : NULL);
+	if(!ret)
+	{
+		return FALSE ;
+	}
 	LLDrawable* old_parent = mDrawable->mParent;
-
 	mDrawable->mParent = parentp; 
-	
-	BOOL ret = mDrawable->mXform.setParent(parentp ? &parentp->mXform : NULL);
+		
 	gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
 	if(	old_parent != parentp &&
 		old_parent || (parentp && parentp->isActive()))
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 72c713f2a69..2b2c2d5a95d 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -237,7 +237,7 @@ class LLViewerObject : public LLPrimitive, public LLRefCount
 	BOOL isProbablyModifiable() const;
 	*/
 
-	virtual void setParent(LLViewerObject* parent);
+	virtual BOOL setParent(LLViewerObject* parent);
 	virtual void addChild(LLViewerObject *childp);
 	virtual void removeChild(LLViewerObject *childp);
 	const_child_list_t& getChildren() const { 	return mChildList; }
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 176f8fb37ba..c2b54ec9c6c 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -5315,12 +5315,13 @@ void LLVOAvatar::hideSkirt()
 	mMeshLOD[MESH_ID_SKIRT]->setVisible(FALSE, TRUE);
 }
 
-void LLVOAvatar::setParent(LLViewerObject* parent)
+BOOL LLVOAvatar::setParent(LLViewerObject* parent)
 {
+	BOOL ret ;
 	if (parent == NULL)
 	{
 		getOffObject();
-		LLViewerObject::setParent(parent);
+		ret = LLViewerObject::setParent(parent);
 		if (isSelf())
 		{
 			gAgent.resetCamera();
@@ -5328,9 +5329,13 @@ void LLVOAvatar::setParent(LLViewerObject* parent)
 	}
 	else
 	{
-		LLViewerObject::setParent(parent);
-		sitOnObject(parent);
+		ret = LLViewerObject::setParent(parent);
+		if(ret)
+		{
+			sitOnObject(parent);
+		}
 	}
+	return ret ;
 }
 
 void LLVOAvatar::addChild(LLViewerObject *childp)
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 56a8e3cd11c..b22c0deb337 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -776,7 +776,7 @@ class LLVOAvatar :
  **/
 
 public:
-	virtual void 	setParent(LLViewerObject* parent);
+	virtual BOOL 	setParent(LLViewerObject* parent);
 	virtual void 	addChild(LLViewerObject *childp);
 	virtual void 	removeChild(LLViewerObject *childp);
 
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index aff8fe8f1d7..f31f09f60e8 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -934,17 +934,20 @@ void LLVOVolume::updateFaceFlags()
 	}
 }
 
-void LLVOVolume::setParent(LLViewerObject* parent)
+BOOL LLVOVolume::setParent(LLViewerObject* parent)
 {
+	BOOL ret = FALSE ;
 	if (parent != getParent())
 	{
-		LLViewerObject::setParent(parent);
-		if (mDrawable)
+		ret = LLViewerObject::setParent(parent);
+		if (ret && mDrawable)
 		{
 			gPipeline.markMoved(mDrawable);
 			gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
 		}
 	}
+
+	return ret ;
 }
 
 // NOTE: regenFaces() MUST be followed by genTriangles()!
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index f20e551671b..5d7b373b3cf 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -107,7 +107,7 @@ class LLVOVolume : public LLViewerObject
 	/*virtual*/ BOOL	isHUDAttachment() const;
 
 				void	generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point);
-	/*virtual*/	void	setParent(LLViewerObject* parent);
+	/*virtual*/	BOOL	setParent(LLViewerObject* parent);
 				S32		getLOD() const							{ return mLOD; }
 	const LLVector3		getPivotPositionAgent() const;
 	const LLMatrix4&	getRelativeXform() const				{ return mRelativeXform; }
-- 
GitLab