Maelstrom: Fixed memory corruption clearing anchor on an element that's been freed.

https://github.com/libsdl-org/Maelstrom/commit/1afff583cf9550f52e892b22c577ae8c1864c163

From 1afff583cf9550f52e892b22c577ae8c1864c163 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sat, 20 Oct 2012 01:02:34 -0700
Subject: [PATCH] Fixed memory corruption clearing anchor on an element that's
 been freed.

---
 screenlib/UIArea.cpp | 37 +++++++++++++++++++++----------------
 screenlib/UIArea.h   |  1 +
 2 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/screenlib/UIArea.cpp b/screenlib/UIArea.cpp
index a8db9661..afca6ff2 100644
--- a/screenlib/UIArea.cpp
+++ b/screenlib/UIArea.cpp
@@ -32,21 +32,17 @@ UIArea::UIArea(UIArea *anchor, int w, int h) : ErrorBase()
 	m_rect.y = 0;
 	m_rect.w = w;
 	m_rect.h = h;
-	m_anchor.element = anchor;
+	m_anchor.element = NULL;
+	SetAnchorElement(anchor);
 	m_anchor.anchorFrom = CENTER;
 	m_anchor.anchorTo = CENTER;
 	m_anchor.offsetX = 0;
 	m_anchor.offsetY = 0;
-	if (anchor) {
-		anchor->AddAnchoredArea(this);
-	}
 }
 
 UIArea::~UIArea()
 {
-	if (m_anchor.element) {
-		m_anchor.element->DelAnchoredArea(this);
-	}
+	SetAnchorElement(NULL);
 	for (int i = 0; i < m_anchoredAreas.length(); ++i) {
 		m_anchoredAreas[i]->SetAnchor(CENTER, CENTER, NULL);
 	}
@@ -72,13 +68,8 @@ UIArea::Load(rapidxml::xml_node<> *node)
 	child = node->first_node("anchor", 0, false);
 	if (child) {
 		attr = child->first_attribute("anchor", 0, false);
-		if (m_anchor.element) {
-			m_anchor.element->DelAnchoredArea(this);
-		}
-		m_anchor.element = GetAnchorElement(attr ? attr->value() : NULL);
-		if (m_anchor.element) {
-			m_anchor.element->AddAnchoredArea(this);
-		} else {
+		SetAnchorElement(GetAnchorElement(attr ? attr->value() : NULL));
+		if (!m_anchor.element) {
 			SetError("Element 'anchor' couldn't find anchor element %s",
 				attr ? attr->value() : "NULL");
 			return false;
@@ -116,7 +107,7 @@ UIArea::GetAnchorElement(const char *name)
 void
 UIArea::SetPosition(int x, int y) {
 	/* Setting the position breaks the anchoring */
-	m_anchor.element = NULL;
+	SetAnchorElement(NULL);
 
 	if (x != m_rect.x || y != m_rect.y) {
 		m_rect.x = x;
@@ -194,7 +185,7 @@ void
 UIArea::SetAnchor(AnchorLocation from, AnchorLocation to, UIArea *anchor,
 						int offsetX, int offsetY)
 {
-	m_anchor.element = anchor;
+	SetAnchorElement(anchor);
 	m_anchor.anchorFrom = from;
 	m_anchor.anchorTo = to;
 	m_anchor.offsetX = offsetX;
@@ -299,6 +290,20 @@ UIArea::LoadAnchorLocation(rapidxml::xml_node<> *node, const char *name, AnchorL
 	return false;
 }
 
+void
+UIArea::SetAnchorElement(UIArea *anchor)
+{
+	if (m_anchor.element) {
+		m_anchor.element->DelAnchoredArea(this);
+	}
+
+	m_anchor.element = anchor;
+
+	if (m_anchor.element) {
+		m_anchor.element->AddAnchoredArea(this);
+	}
+}
+
 void
 UIArea::GetAnchorLocation(AnchorLocation spot, int *x, int *y) const
 {
diff --git a/screenlib/UIArea.h b/screenlib/UIArea.h
index 4bd24aaf..d3b119ae 100644
--- a/screenlib/UIArea.h
+++ b/screenlib/UIArea.h
@@ -117,6 +117,7 @@ class UIArea : public ErrorBase
 	bool LoadString(rapidxml::xml_node<> *node, const char *name, char *&value);
 	bool LoadAnchorLocation(rapidxml::xml_node<> *node, const char *name, AnchorLocation &value);
 
+	void SetAnchorElement(UIArea *anchor);
 	void GetAnchorLocation(AnchorLocation spot, int *x, int *y) const;
 	void CalculateAnchor(bool triggerRectChanged = true);
 	virtual void OnRectChanged();