Commits

Anonymous committed 3a09a5b

Crashfix: showToastsTop/Bottom, don't iterate over mToastList. The member can change during recursive calls, invalidating iterators.

Comments (0)

Files changed (1)

indra/newview/llscreenchannel.cpp

 
 	LLDockableFloater* floater = dynamic_cast<LLDockableFloater*>(LLDockableFloater::getInstanceHandle().get());
 
-	for(it = mToastList.rbegin(); it != mToastList.rend(); ++it)
+	// Use a local variable instead of mToastList.
+	// mToastList can be modified during recursive calls and then all iteratos will be invalidated.
+	std::vector<ToastElem> vToastList( mToastList );
+
+	for(it = vToastList.rbegin(); it != vToastList.rend(); ++it)
 	{
-		if(it != mToastList.rbegin())
+		if(it != vToastList.rbegin())
 		{
 			LLToast* toast = (it-1)->getToast();
 			if (!toast)
 
 		if(floater && floater->overlapsScreenChannel())
 		{
-			if(it == mToastList.rbegin())
+			if(it == vToastList.rbegin())
 			{
 				// move first toast above docked floater
 				S32 shift = floater->getRect().getHeight();
 
 		if(!stop_showing_toasts)
 		{
-			if( it != mToastList.rend()-1)
+			if( it != vToastList.rend()-1)
 			{
 				S32 toast_top = toast->getRect().mTop + gSavedSettings.getS32("ToastGap");
 				stop_showing_toasts = toast_top > getRect().mTop;
 		} 
 
 		// at least one toast should be visible
-		if(it == mToastList.rbegin())
+
+		if(it == vToastList.rbegin())
 		{
 			stop_showing_toasts = false;
 		}
 	}
 
 	// Dismiss toasts we don't have space for (STORM-391).
-	if(it != mToastList.rend())
+	if(it != vToastList.rend())
 	{
 		mHiddenToastsNum = 0;
-		for(; it != mToastList.rend(); it++)
+
+		for(; it != vToastList.rend(); it++)
 		{
 			LLToast* toast = it->getToast();
 			if (toast)
 
 	LLDockableFloater* floater = dynamic_cast<LLDockableFloater*>(LLDockableFloater::getInstanceHandle().get());
 
-	for(it = mToastList.rbegin(); it != mToastList.rend(); ++it)
+	// Use a local variable instead of mToastList.
+	// mToastList can be modified during recursive calls and then all iteratos will be invalidated.
+	std::vector<ToastElem> vToastList( mToastList );
+
+	for(it = vToastList.rbegin(); it != vToastList.rend(); ++it)
 	{
-		if(it != mToastList.rbegin())
+		if(it != vToastList.rbegin())
 		{
 			LLToast* toast = (it-1)->getToast();
 			if (!toast)
 
 		if(floater && floater->overlapsScreenChannel())
 		{
-			if(it == mToastList.rbegin())
+			if(it == vToastList.rbegin())
 			{
 				// move first toast above docked floater
 				S32 shift = -floater->getRect().getHeight();
 
 		if(!stop_showing_toasts)
 		{
-			if( it != mToastList.rend()-1)
+			if( it != vToastList.rend()-1)
 			{
 				S32 toast_bottom = toast->getRect().mBottom - gSavedSettings.getS32("ToastGap");
 				stop_showing_toasts = toast_bottom < channel_rect.mBottom;
 		} 
 
 		// at least one toast should be visible
-		if(it == mToastList.rbegin())
+		if(it == vToastList.rbegin())
 		{
 			stop_showing_toasts = false;
 		}
 
 	// Dismiss toasts we don't have space for (STORM-391).
 	std::vector<LLToast*> toasts_to_hide;
-	if(it != mToastList.rend())
+
+	if(it != vToastList.rend())
 	{
 		mHiddenToastsNum = 0;
-		for(; it != mToastList.rend(); it++)
+
+		for(; it != vToastList.rend(); it++)
 		{
 			LLToast* toast = it->getToast();
 			if (toast)