changeset 15446:a77b7f93cb3f draft

(svn r20089) -Fix [FS#3932]: Access of already freed memory, esp. due to hidden destructor call from Swap().
author frosch <frosch@openttd.org>
date Thu, 08 Jul 2010 18:38:38 +0000
parents 6dcdc3eb8d53
children 8336429b0ffb
files src/network/core/tcp_content.cpp src/network/core/tcp_content.h src/network/network_content.cpp
diffstat 3 files changed, 21 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/network/core/tcp_content.cpp
+++ b/src/network/core/tcp_content.cpp
@@ -27,6 +27,21 @@
 	free(this->tags);
 }
 
+/**
+ * Copy data from other #ContentInfo and take ownership of allocated stuff.
+ * @param other Source to copy from. #dependencies and #tags will be NULLed.
+ */
+void ContentInfo::TransferFrom(ContentInfo *other)
+{
+	if (other != this) {
+		free(this->dependencies);
+		free(this->tags);
+		memcpy(this, other, sizeof(ContentInfo));
+		other->dependencies = NULL;
+		other->tags = NULL;
+	}
+}
+
 size_t ContentInfo::Size() const
 {
 	size_t len = 0;
--- a/src/network/core/tcp_content.h
+++ b/src/network/core/tcp_content.h
@@ -88,6 +88,8 @@
 	/** Free everything allocated */
 	~ContentInfo();
 
+	void TransferFrom(ContentInfo *other);
+
 	/**
 	 * Get the size of the data as send over the network.
 	 * @return the size.
--- a/src/network/network_content.cpp
+++ b/src/network/network_content.cpp
@@ -135,15 +135,13 @@
 			/*
 			 * As ici might be selected by the content window we cannot delete that.
 			 * However, we want to keep most of the values of ci, except the values
-			 * we (just) already preserved. As there are already allocated blobs of
-			 * memory and more may be added, we cannot simply copy ci to ici as that
-			 * might cause a leak of memory. As such we need to swap the data and
-			 * then delete the memory we allocated here.
+			 * we (just) already preserved.
+			 * So transfer data and ownership of allocated memory from ci to ici.
 			 */
-			Swap(*ici, *ci);
+			ici->TransferFrom(ci);
 			delete ci;
 
-			this->OnReceiveContentInfo(ci);
+			this->OnReceiveContentInfo(ici);
 			return true;
 		}
 	}