Przeglądaj źródła

* Possible fix to ers/status_change crashing. [FlavioJS]
- this patch is untested. Didn't find anyone willing to test it and I can't reproduce the crash so can't test the patch.
symptom:
status_change_entry.timer is being modified after the entry is freed.
ers uses that memory location as a pointer when the entry is freed, it crashes when accessing the contents when it points to an invalid location.
assumption:
status_change_start starts an already existing status.
as a consequence of something called inside status_change_start the status is ended.
when the sce is finally being modified, it's modifying a freed entry.

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@12058 54d463be-8e91-2dee-dedb-b68131a5f0ec

FlavioJS 17 lat temu
rodzic
commit
a85a22d75a
2 zmienionych plików z 31 dodań i 10 usunięć
  1. 12 0
      Changelog-Trunk.txt
  2. 19 10
      src/map/status.c

+ 12 - 0
Changelog-Trunk.txt

@@ -3,6 +3,18 @@ Date	Added
 AS OF SVN REV. 5091, WE ARE NOW USING TRUNK.  ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
 AS OF SVN REV. 5091, WE ARE NOW USING TRUNK.  ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 
 
+2008/01/12
+	* Possible fix to ers/status_change crashing. [FlavioJS]
+	- this patch is untested. Didn't find anyone willing to test it and I can't 
+	  reproduce the crash so can't test the patch.
+	  symptom:
+	   status_change_entry.timer is being modified after the entry is freed.
+	   ers uses that memory location as a pointer when the entry is freed, 
+	   it crashes when accessing the contents when it points to an invalid location.
+	  assumption:
+	   status_change_start starts an already existing status.
+	   as a consequence of something called inside status_change_start the status is ended.
+	   when the sce is finally being modified, it's modifying a freed entry.
 2008/01/11
 2008/01/11
 	* Implemented the extra damage bonus to TK_JUMPKICK when it is used while
 	* Implemented the extra damage bonus to TK_JUMPKICK when it is used while
 	  running (however what the bonus's equation is has been lost to time, so
 	  running (however what the bonus's equation is has been lost to time, so

+ 19 - 10
src/map/status.c

@@ -5000,15 +5000,18 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 				if(sce->val1 > val1)
 				if(sce->val1 > val1)
 					return 1; //Return true to not mess up skill animations. [Skotlex
 					return 1; //Return true to not mess up skill animations. [Skotlex
 		}
 		}
-		(sc->count)--;
-		if (sce->timer != -1)
-			delete_timer(sce->timer, status_change_timer);
-		sce->timer = -1;
 	}
 	}
 	//NOTE: avoiding returning after this point, or if you must return a failure, use this to properly cleanup any existing data. 
 	//NOTE: avoiding returning after this point, or if you must return a failure, use this to properly cleanup any existing data. 
-#define sc_start_abort(ret) { \
-	if (sce) { ers_free(sc_data_ers, sce); sc->data[type] = NULL; } \
-	return ret; }
+#define sc_start_abort(ret) \
+	do{ \
+		if((sce=sc->data[type])){ \
+			--(sc->count); \
+			sc->data[type] = NULL; \
+			if( sce->timer != INVALID_TIMER ) delete_timer(sce->timer, status_change_timer); \
+			ers_free(sc_data_ers, sce); \
+			return ret; \
+		} \
+	}while(0)
 
 
 	vd = status_get_viewdata(bl);
 	vd = status_get_viewdata(bl);
 	calc_flag = StatusChangeFlagTable[type];
 	calc_flag = StatusChangeFlagTable[type];
@@ -6101,10 +6104,16 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 	else if (sd) //Send packet to self otherwise (disguised player?)
 	else if (sd) //Send packet to self otherwise (disguised player?)
 		clif_status_load(bl,StatusIconChangeTable[type],1);
 		clif_status_load(bl,StatusIconChangeTable[type],1);
 
 
-	(sc->count)++;
-
-	if (!sce) //Not null when overwriting existing sc.
+	if((sce=sc->data[type]))
+	{// reuse old sc
+		if( sce->timer != INVALID_TIMER )
+			delete_timer(sce->timer, status_change_timer);
+	}
+	else
+	{// new sc
+		++(sc->count);
 		sce = sc->data[type] = ers_alloc(sc_data_ers, struct status_change_entry);
 		sce = sc->data[type] = ers_alloc(sc_data_ers, struct status_change_entry);
+	}
 	sce->val1 = val1;
 	sce->val1 = val1;
 	sce->val2 = val2;
 	sce->val2 = val2;
 	sce->val3 = val3;
 	sce->val3 = val3;