summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorfrosch <frosch@openttd.org>2010-07-08 18:38:38 +0000
committerfrosch <frosch@openttd.org>2010-07-08 18:38:38 +0000
commit4ce5c6d93dea944df7de559ea62b625a3643ce52 (patch)
tree903161acc876495d4b95056597c139fb49b7f10e /src
parent02e4371ecb7c36d1889c3c9f8d1eb30c92da4ba3 (diff)
downloadopenttd-4ce5c6d93dea944df7de559ea62b625a3643ce52.tar.xz
(svn r20089) -Fix [FS#3932]: Access of already freed memory, esp. due to hidden destructor call from Swap().
Diffstat (limited to 'src')
-rw-r--r--src/network/core/tcp_content.cpp15
-rw-r--r--src/network/core/tcp_content.h2
-rw-r--r--src/network/network_content.cpp10
3 files changed, 21 insertions, 6 deletions
diff --git a/src/network/core/tcp_content.cpp b/src/network/core/tcp_content.cpp
index 897570a91..b5bf52999 100644
--- a/src/network/core/tcp_content.cpp
+++ b/src/network/core/tcp_content.cpp
@@ -27,6 +27,21 @@ ContentInfo::~ContentInfo()
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;
diff --git a/src/network/core/tcp_content.h b/src/network/core/tcp_content.h
index 3b82696df..24b87f16f 100644
--- a/src/network/core/tcp_content.h
+++ b/src/network/core/tcp_content.h
@@ -88,6 +88,8 @@ struct ContentInfo {
/** Free everything allocated */
~ContentInfo();
+ void TransferFrom(ContentInfo *other);
+
/**
* Get the size of the data as send over the network.
* @return the size.
diff --git a/src/network/network_content.cpp b/src/network/network_content.cpp
index f70f0e724..a7032a60f 100644
--- a/src/network/network_content.cpp
+++ b/src/network/network_content.cpp
@@ -135,15 +135,13 @@ DEF_CONTENT_RECEIVE_COMMAND(Client, PACKET_CONTENT_SERVER_INFO)
/*
* 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;
}
}