From c56d2eecb005c6bbb8000c70cedc6f537123ba57 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 6 Oct 2016 08:50:46 +0200 Subject: [PATCH 1/3] - rewrote AActor::DestroyAllInventory so that it clears the item's link to its owner and the owner's inventory list before destroying them. There have been reports about crashes in here with Linux that point to some of the code that gets called here doing unwanted things on the owner, so with these links cleared that should no longer be possible. --- src/p_mobj.cpp | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 496f52e86..022504919 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -685,11 +685,30 @@ bool AActor::TakeInventory(PClassActor *itemclass, int amount, bool fromdecorate void AActor::DestroyAllInventory () { - while (Inventory != NULL) + AInventory *inv = Inventory; + if (inv != nullptr) { - AInventory *item = Inventory; - item->Destroy (); - assert (item != Inventory); + TArray toDelete; + + // Delete the list in a two stage approach. + // This is necessary because an item may destroy another item (e.g. sister weapons) + // which would break the list and leave parts of it undestroyed, maybe doing bad things later. + while (inv != nullptr) + { + toDelete.Push(inv); + AInventory *item = inv->Inventory; + inv->Inventory = nullptr; + inv->Owner = nullptr; + inv = item; + } + for (auto p : toDelete) + { + // the item may already have been deleted by another one, so check this here to avoid problems. + if (!(p->ObjectFlags & OF_EuthanizeMe)) + { + p->Destroy(); + } + } } } From d7bb5bb41ed8e853095d5207b74a2079589c716e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 6 Oct 2016 12:08:38 +0200 Subject: [PATCH 2/3] - fixed: ZCC_OpInfoType::FindBestProto was missing checks for exact match of the required conversion before testing if it is a F32->F64 conversion. Of course, since 0 means that there is no conversion it also means that there is no data that could be checked. --- src/zscript/zcc_expr.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/zscript/zcc_expr.cpp b/src/zscript/zcc_expr.cpp index 0cd399d64..e1a091b18 100644 --- a/src/zscript/zcc_expr.cpp +++ b/src/zscript/zcc_expr.cpp @@ -162,11 +162,11 @@ ZCC_OpProto *ZCC_OpInfoType::FindBestProto( // [[float32 (op) int]] will choose the integer version instead of the floating point // version, which we do not want. int test_dist1 = dist1, test_dist2 = dist2; - if (routes[0][cur_route1][0]->ConvertConstant == FtoD) + if (test_dist1 > 0 && routes[0][cur_route1][0]->ConvertConstant == FtoD) { test_dist1--; } - if (routes[1][cur_route2][0]->ConvertConstant == FtoD) + if (test_dist2 > 0 && routes[1][cur_route2][0]->ConvertConstant == FtoD) { test_dist2--; } From 99c4d03ad4b3151375edb8b015bd25021c2e3193 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 6 Oct 2016 21:20:49 +0200 Subject: [PATCH 3/3] - fixed: DCeiling's main constructor could leave some fields uninitialized. --- src/p_ceiling.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/p_ceiling.cpp b/src/p_ceiling.cpp index 32e5d62be..e90dd2096 100644 --- a/src/p_ceiling.cpp +++ b/src/p_ceiling.cpp @@ -214,6 +214,12 @@ DCeiling::DCeiling (sector_t *sec, double speed1, double speed2, int silent) m_Speed = m_Speed1 = speed1; m_Speed2 = speed2; m_Silent = silent; + m_BottomHeight = 0; + m_TopHeight = 0; + m_Direction = 0; + m_Texture = FNullTextureID(); + m_Tag = 0; + m_OldDirection = 0; } //============================================================================