Mercurial > hg > openttd
changeset 5393:b38ae32d2a0e draft
(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.
author | rubidium <rubidium@openttd.org> |
---|---|
date | Wed, 27 Dec 2006 18:25:17 +0000 |
parents | 9dc3ecf487f0 |
children | 6a8700f3706c |
files | newgrf_config.c newgrf_config.h |
diffstat | 2 files changed, 47 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/newgrf_config.c +++ b/newgrf_config.c @@ -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 +++ b/newgrf_config.h @@ -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);