(svn r7582) -Fix (r7490): appending static GRFs to the list of to-be loaded GRF for a game could result in duplicate GRFs in that list, which can cause a segmentation fault while loading the GRFs.
authorrubidium
Wed, 27 Dec 2006 18:25:17 +0000
changeset 5393 cf584337ea2c
parent 5392 dd535f122f1d
child 5394 bce82a9368c7
(svn r7582) -Fix (r7490): appending static GRFs to the list of to-be loaded GRF for a game could result in duplicate GRFs in that list, which can cause a segmentation fault while loading the GRFs.
newgrf_config.c
newgrf_config.h
--- a/newgrf_config.c	Wed Dec 27 16:18:59 2006 +0000
+++ b/newgrf_config.c	Wed Dec 27 18:25:17 2006 +0000
@@ -131,6 +131,50 @@
 	return dst;
 }
 
+/**
+ * Removes duplicates from lists of GRFConfigs. These duplicates
+ * are introduced when the _grfconfig_static GRFs are appended
+ * to the _grfconfig on a newgame or savegame. As the parameters
+ * of the static GRFs could be different that the parameters of
+ * the ones used non-statically. This can result in desyncs in
+ * multiplayers, so the duplicate static GRFs have to be removed.
+ *
+ * This function _assumes_ that all static GRFs are placed after
+ * the non-static GRFs.
+ *
+ * @param list the list to remove the duplicates from
+ */
+static void RemoveDuplicatesFromGRFConfigList(GRFConfig *list)
+{
+	GRFConfig *prev;
+	GRFConfig *cur;
+
+	if (list == NULL) return;
+
+	for (prev = list, cur = list->next; cur != NULL; prev = cur, cur = cur->next) {
+		if (cur->grfid != list->grfid) continue;
+		assert(HASBIT(cur->flags, GCF_STATIC));
+		prev->next = cur->next;
+		ClearGRFConfig(&cur);
+		cur = prev; // Just go back one so it continues as normal later on
+	}
+
+	RemoveDuplicatesFromGRFConfigList(list->next);
+}
+
+/**
+ * Appends the static GRFs to a list of GRFs
+ * @param dst the head of the list to add to
+ */
+void AppendStaticGRFConfigs(GRFConfig **dst)
+{
+	GRFConfig **tail = dst;
+	while (*tail != NULL) tail = &(*tail)->next;
+
+	CopyGRFConfigList(tail, _grfconfig_static);
+	RemoveDuplicatesFromGRFConfigList(*dst);
+}
+
 
 /* Reset the current GRF Config to either blank or newgame settings */
 void ResetGRFConfig(bool defaults)
@@ -138,7 +182,7 @@
 	GRFConfig **c = &_grfconfig;
 
 	if (defaults) c = CopyGRFConfigList(c, _grfconfig_newgame);
-	CopyGRFConfigList(c, _grfconfig_static);
+	AppendStaticGRFConfigs(&_grfconfig);
 }
 
 
@@ -400,6 +444,7 @@
 
 	ClearGRFConfigList(&_grfconfig);
 	_grfconfig = first;
+	AppendStaticGRFConfigs(&_grfconfig);
 }
 
 const ChunkHandler _newgrf_chunk_handlers[] = {
--- a/newgrf_config.h	Wed Dec 27 16:18:59 2006 +0000
+++ b/newgrf_config.h	Wed Dec 27 18:25:17 2006 +0000
@@ -44,6 +44,7 @@
 const GRFConfig *FindGRFConfig(uint32 grfid, uint8 *md5sum);
 GRFConfig *GetGRFConfig(uint32 grfid);
 GRFConfig **CopyGRFConfigList(GRFConfig **dst, const GRFConfig *src);
+void AppendStaticGRFConfigs(GRFConfig **dst);
 void ClearGRFConfig(GRFConfig **config);
 void ClearGRFConfigList(GRFConfig **config);
 void ResetGRFConfig(bool defaults);