From 07b463722e3e87aaea608981a1020f1b482781ba Mon Sep 17 00:00:00 2001
From: Vadim Savchuk <vsavchuk@productengine.com>
Date: Fri, 23 Apr 2010 17:18:37 +0300
Subject: [PATCH] Fixed bug EXT-6798 (Crash in LLTeleportHistoryStorage).

Reason: Attempt to purge empty teleport history resulted in inconsistent history state.
There were two consequences:
1) Further teleports would not properly update the history.
2) Subscribers of history changes were notified of the invalid change and that led to the crash.

My changes:
- added a sanity check to LLTeleportHistoryStorage::onTeleportHistoryChange() to prevent the crash
- purging empty teleport history now does nothing, hence the history doesn't become inconsistent
- removed a redundant (but harmless) call to onTeleportHistoryChanged() from LLNavigationBar::draw() because it's called by LLTeleportHistory::purgeItems() anyway

Reviewed by Mike at https://codereview.productengine.com/secondlife/r/304/

--HG--
branch : product-engine
---
 indra/newview/llnavigationbar.cpp          |  1 -
 indra/newview/llteleporthistory.cpp        | 12 ++++++++++++
 indra/newview/llteleporthistorystorage.cpp |  7 +++++++
 3 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp
index e11df06d868..0341f2c693d 100644
--- a/indra/newview/llnavigationbar.cpp
+++ b/indra/newview/llnavigationbar.cpp
@@ -375,7 +375,6 @@ void LLNavigationBar::draw()
 	if(mPurgeTPHistoryItems)
 	{
 		LLTeleportHistory::getInstance()->purgeItems();
-		onTeleportHistoryChanged();
 		mPurgeTPHistoryItems = false;
 	}
 
diff --git a/indra/newview/llteleporthistory.cpp b/indra/newview/llteleporthistory.cpp
index dcc85392f7e..15684337f4a 100644
--- a/indra/newview/llteleporthistory.cpp
+++ b/indra/newview/llteleporthistory.cpp
@@ -136,6 +136,7 @@ void LLTeleportHistory::updateCurrentLocation(const LLVector3d& new_pos)
 		if (mCurrentItem < 0 || mCurrentItem >= (int) mItems.size()) // sanity check
 		{
 			llwarns << "Invalid current item. (this should not happen)" << llendl;
+			llassert(!"Invalid current teleport histiry item");
 			return;
 		}
 		LLVector3 new_pos_local = gAgent.getPosAgentFromGlobal(new_pos);
@@ -166,6 +167,17 @@ void LLTeleportHistory::onHistoryChanged()
 
 void LLTeleportHistory::purgeItems()
 {
+	if (mItems.size() == 0) // no entries yet (we're called before login)
+	{
+		// If we don't return here the history will get into inconsistent state, hence:
+		// 1) updateCurrentLocation() will malfunction,
+		//    so further teleports will not properly update the history;
+		// 2) mHistoryChangedSignal subscribers will be notified
+		//    of such an invalid change. (EXT-6798)
+		// Both should not happen.
+		return;
+	}
+
 	if (mItems.size() > 0)
 	{
 		mItems.erase(mItems.begin(), mItems.end()-1);
diff --git a/indra/newview/llteleporthistorystorage.cpp b/indra/newview/llteleporthistorystorage.cpp
index c635f914239..430d62e15e1 100644
--- a/indra/newview/llteleporthistorystorage.cpp
+++ b/indra/newview/llteleporthistorystorage.cpp
@@ -89,6 +89,13 @@ void LLTeleportHistoryStorage::onTeleportHistoryChange()
 	if (!th)
 		return;
 
+	// Hacky sanity check. (EXT-6798)
+	if (th->getItems().size() == 0)
+	{
+		llassert(!"Inconsistent teleport history state");
+		return;
+	}
+
 	const LLTeleportHistoryItem &item = th->getItems()[th->getCurrentItemIndex()];
 
 	addItem(item.mTitle, item.mGlobalPos);
-- 
GitLab