foxygit / doom Log in
commit 1bcff874c52aca3134cee636178ab5d6272fef58
Author:     Simon Howard <fraggle@soulsphere.org>
AuthorDate: Sun Apr 26 18:55:43 2015 -0400
Commit:     Simon Howard <fraggle@soulsphere.org>
CommitDate: Sun Apr 26 18:55:43 2015 -0400

    Don't read currentthinker->next after Z_Free().

    Save the next pointer in the P_RunThinkers() loop when iterating through
    thinkers, so that if the current thinker is freed we can still advance
    to the next thinker without dereferencing freed memory.
---
 src/doom/p_tick.c    | 8 +++++---
 src/heretic/p_tick.c | 6 ++++--
 src/hexen/p_tick.c   | 7 +++++--
 src/strife/p_tick.c  | 7 +++++--
 4 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/src/doom/p_tick.c b/src/doom/p_tick.c
index 22893500..c933cfe9 100644
--- a/src/doom/p_tick.c
+++ b/src/doom/p_tick.c
@@ -93,24 +93,26 @@ void P_AllocateThinker (thinker_t*	thinker)
 //
 void P_RunThinkers (void)
 {
-    thinker_t*	currentthinker;
+    thinker_t *currentthinker, *nextthinker;

     currentthinker = thinkercap.next;
     while (currentthinker != &thinkercap)
     {
+        nextthinker = currentthinker->next;
+
 	if ( currentthinker->function.acv == (actionf_v)(-1) )
 	{
 	    // time to remove it
 	    currentthinker->next->prev = currentthinker->prev;
 	    currentthinker->prev->next = currentthinker->next;
-	    Z_Free (currentthinker);
+	    Z_Free(currentthinker);
 	}
 	else
 	{
 	    if (currentthinker->function.acp1)
 		currentthinker->function.acp1 (currentthinker);
 	}
-	currentthinker = currentthinker->next;
+	currentthinker = nextthinker;
     }
 }

diff --git a/src/heretic/p_tick.c b/src/heretic/p_tick.c
index c93a211f..323cc1e6 100644
--- a/src/heretic/p_tick.c
+++ b/src/heretic/p_tick.c
@@ -110,11 +110,13 @@ void P_AllocateThinker(thinker_t * thinker)

 void P_RunThinkers(void)
 {
-    thinker_t *currentthinker;
+    thinker_t *currentthinker, *nextthinker;

     currentthinker = thinkercap.next;
     while (currentthinker != &thinkercap)
     {
+        nextthinker = currentthinker->next;
+
         if (currentthinker->function == (think_t) - 1)
         {                       // time to remove it
             currentthinker->next->prev = currentthinker->prev;
@@ -126,7 +128,7 @@ void P_RunThinkers(void)
             if (currentthinker->function)
                 currentthinker->function(currentthinker);
         }
-        currentthinker = currentthinker->next;
+        currentthinker = nextthinker;
     }
 }

diff --git a/src/hexen/p_tick.c b/src/hexen/p_tick.c
index 95242ccd..c58d6e82 100644
--- a/src/hexen/p_tick.c
+++ b/src/hexen/p_tick.c
@@ -86,11 +86,13 @@ void P_Ticker(void)

 static void RunThinkers(void)
 {
-    thinker_t *currentthinker;
+    thinker_t *currentthinker, *nextthinker;

     currentthinker = thinkercap.next;
     while (currentthinker != &thinkercap)
     {
+        nextthinker = currentthinker->next;
+
         if (currentthinker->function == (think_t) - 1)
         {                       // Time to remove it
             currentthinker->next->prev = currentthinker->prev;
@@ -101,7 +103,8 @@ static void RunThinkers(void)
         {
             currentthinker->function(currentthinker);
         }
-        currentthinker = currentthinker->next;
+
+        currentthinker = nextthinker;
     }
 }

diff --git a/src/strife/p_tick.c b/src/strife/p_tick.c
index f4ed2711..c0dd4786 100644
--- a/src/strife/p_tick.c
+++ b/src/strife/p_tick.c
@@ -99,11 +99,13 @@ void P_AllocateThinker (thinker_t*	thinker)
 //
 void P_RunThinkers (void)
 {
-    thinker_t*  currentthinker;
+    thinker_t *currentthinker, *nextthinker;

     currentthinker = thinkercap.next;
     while (currentthinker != &thinkercap)
     {
+        nextthinker = currentthinker->next;
+
         if ( currentthinker->function.acv == (actionf_v)(-1) )
         {
             // time to remove it
@@ -116,7 +118,8 @@ void P_RunThinkers (void)
             if (currentthinker->function.acp1)
                 currentthinker->function.acp1 (currentthinker);
         }
-        currentthinker = currentthinker->next;
+
+        currentthinker = nextthinker;
     }
 }