Crossfire Mailing List Archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

CF: bug fixes for crossfire 0.92.4



Here is a patch for server/spell_util.c and server/skills.c.  I hope
that nobody will complain because of the size of the message in their
mailbox (it's only 6K).

I found that several parts of the code are using get_map_op() without
checking if the coordinates are within the map or not.  Since
get_map_op() is a macro which adds pointers, nasty things can happen
with out-of-bounds accesses to the map data.  I crashed the game
several times when searching for traps or using the oratory skill near
one corner of the map or when a bomb explodes on a map that has no
walls on the edges.  This also happened with monsters reading scrolls.

These two patches add the necessary calls to the macro out_of_map() in
various parts of the code, before the calls to get_map_ob().  I hope
that I didn't forget any of them.

Note to the programmers adding new spells or skills: be very careful
when you call get_map_ob()!  If you check first with one function such
as wall(), blocks_view() or blocked(), then you are safe because they
all call out_of_map().  But if you don't, then make sure that you
check out_of_map() before calling get_map_ob().  Otherwise, Bad Things
happen...

---------- cut here ---------- cut here ---------- cut here ----------
*** server/spell_util.c.orig	Fri Jul  5 11:12:11 1996
--- server/spell_util.c	Fri Jul  5 11:25:05 1996
***************
*** 1360,1365 ****
--- 1360,1369 ----
    if(blocked(op->map,op->x,op->y)) {
      object *tmp;
      remove_ob(op);
+     if(out_of_map(op->map,op->x,op->y)) {
+       free_object(op);
+       return;
+     }
      if(explode_object(op))
        return;
      for(tmp=get_map_ob(op->map,op->x,op->y);tmp!=NULL;tmp=tmp->above)
***************
*** 1402,1407 ****
--- 1406,1415 ----
    }
    if(blocked(op->map,op->x,op->y)) {
      object *tmp;
+     if(out_of_map(op->map,op->x,op->y)) {
+       free_object(op);
+       return;
+     }
      if(explode_object(op))
        return;
      for(tmp=get_map_ob(op->map,op->x,op->y);tmp!=NULL;tmp=tmp->above)
***************
*** 1458,1468 ****
      if(!tmp || !QUERY_FLAG(tmp,FLAG_MONSTER)) tmp=op;
    }
    else
!     for(tmp=get_map_ob(op->map,op->x+freearr_x[dir],op->y+freearr_y[dir]);
!         tmp!=NULL;
!         tmp=tmp->above)
!       if(tmp->type==PLAYER)
!         break;
    if(tmp==NULL)               /* didn't find a player there, look in current square for a player */
      for(tmp=get_map_ob(op->map,op->x,op->y);tmp!=NULL;tmp=tmp->above)
        if(tmp->type==PLAYER)
--- 1466,1481 ----
      if(!tmp || !QUERY_FLAG(tmp,FLAG_MONSTER)) tmp=op;
    }
    else
!     {
!       if (out_of_map(op->map,op->x+freearr_x[dir],op->y+freearr_y[dir]))
! 	tmp = NULL;
!       else
! 	for(tmp=get_map_ob(op->map,op->x+freearr_x[dir],op->y+freearr_y[dir]);
! 	    tmp!=NULL;
! 	    tmp=tmp->above)
! 	  if(tmp->type==PLAYER)
! 	    break;
!     }
    if(tmp==NULL)               /* didn't find a player there, look in current square for a player */
      for(tmp=get_map_ob(op->map,op->x,op->y);tmp!=NULL;tmp=tmp->above)
        if(tmp->type==PLAYER)
*** server/skills.c.orig	Fri Jul  5 10:16:00 1996
--- server/skills.c	Fri Jul  5 11:27:48 1996
***************
*** 179,184 ****
--- 179,190 ----
  
      sprintf(buf, "There is no lock there.");
  
+     if (out_of_map(pl->map,x,y))
+       {
+ 	new_draw_info(NDI_UNIQUE, 0,pl,buf);
+ 	return 0;
+       }
+ 
      for(tmp=get_map_ob(pl->map,x,y); tmp; tmp=tmp->above) {
        if(!tmp) continue;
        switch(tmp->type) { 
***************
*** 345,350 ****
--- 351,360 ----
    remove_ob(pl);
    SET_FLAG(pl,FLAG_FLYING);
    for(i=0;i<=spaces;i++) { 
+       if(out_of_map(pl->map,pl->x+dx,pl->y+dy)) {
+ 	(void) stop_jump(pl,i,spaces);
+ 	return calc_skill_exp(pl,NULL);
+       } 
        for(tmp=get_map_ob(pl->map,pl->x+dx,pl->y+dy);
          tmp;tmp=tmp->above) { 
  	   if(wall(tmp->map,tmp->x,tmp->y)) {           /* Jump into wall*/ 
***************
*** 373,383 ****
  	     return calc_skill_exp(pl,NULL);
  	   }
        }
!       if(out_of_map(pl->map,pl->x+dx,pl->y+dy)) {
!   		(void) stop_jump(pl,i,spaces);
! 		return calc_skill_exp(pl,NULL);
!       } else  
!         pl->x+=dx,pl->y+=dy;
    }
    (void) stop_jump(pl,i,spaces);
    return calc_skill_exp(pl,NULL);
--- 383,390 ----
  	     return calc_skill_exp(pl,NULL);
  	   }
        }
!       pl->x+=dx;
!       pl->y+=dy;
    }
    (void) stop_jump(pl,i,spaces);
    return calc_skill_exp(pl,NULL);
***************
*** 554,559 ****
--- 561,567 ----
    object *tmp;
   
  	if(pl->type!=PLAYER) return 0;	/* only players use this skill */ 
+ 	if(out_of_map(pl->map,x,y)) return 0;
  
          for(tmp=get_map_ob(pl->map,x,y);tmp;tmp=tmp->above) { 
          	if(!tmp) return 0;
***************
*** 633,642 ****
          if(pl->type!=PLAYER) return 0;    /* only players use this skill */
  
          new_draw_info_format(NDI_UNIQUE,0,pl, "You sing");
!         for(i=dir;i<(dir+MIN(SK_level(pl),SIZEOFFREE));i++) 
              for(tmp=get_map_ob(pl->map,pl->x+freearr_x[i],pl->y+freearr_y[i]);
  		  tmp;tmp=tmp->above) {
-                 if(!tmp) return 0;
  		if(!QUERY_FLAG(tmp,FLAG_MONSTER)) continue;
   		/* can't affect players */
                  if(tmp->type==PLAYER || tmp->stats.Int) continue;   
--- 641,651 ----
          if(pl->type!=PLAYER) return 0;    /* only players use this skill */
  
          new_draw_info_format(NDI_UNIQUE,0,pl, "You sing");
!         for(i=dir;i<(dir+MIN(SK_level(pl),SIZEOFFREE));i++) {
! 	    if (out_of_map(pl->map,pl->x+freearr_x[i],pl->y+freearr_y[i]))
! 	      continue;
              for(tmp=get_map_ob(pl->map,pl->x+freearr_x[i],pl->y+freearr_y[i]);
  		  tmp;tmp=tmp->above) {
  		if(!QUERY_FLAG(tmp,FLAG_MONSTER)) continue;
   		/* can't affect players */
                  if(tmp->type==PLAYER || tmp->stats.Int) continue;   
***************
*** 667,672 ****
--- 676,682 ----
                    	"Too bad the %s is'nt listening!\n",query_name(tmp));
  		}
  	    }
+ 	}
  	return exp;
  }
  
***************
*** 1024,1050 ****
    int i,x,y,success=0;    
  
     for(i=0;i<9;i++) {
!       x = op->x + freearr_x[i]; 
!       y = op->y + freearr_y[i]; 
!       if(out_of_map(op->map,x,y)) {
! 	new_draw_info(NDI_UNIQUE,0,op,"There are no traps there!");
! 	return 0;
!       }
  
!   /*  Check everything in the square for trapness */
!    for(tmp = get_map_ob(op->map,x,y);tmp!=NULL;tmp=tmp->above) { 
  
!       /* And now we'd better do an inventory traversal of each
!        * of these objects' inventory */
  
!       for(tmp2=tmp->inv;tmp2!=NULL;tmp2=tmp2->below) 
           if(tmp2->type==RUNE&&tmp2->stats.Cha<=1) {
                trap_show(tmp2,tmp);
                if(trap_disarm(op,tmp2,1))
  		   success += calc_skill_exp(op,tmp2);
           }
  
!       if(tmp->type==RUNE&&tmp->stats.Cha<=1) {
           trap_show(tmp,tmp);
           if (trap_disarm(op,tmp,1))
  		   success += calc_skill_exp(op,tmp);
--- 1034,1058 ----
    int i,x,y,success=0;    
  
     for(i=0;i<9;i++) {
!      x = op->x + freearr_x[i]; 
!      y = op->y + freearr_y[i]; 
!      if(out_of_map(op->map,x,y))
!        continue;
  
!      /*  Check everything in the square for trapness */
!      for(tmp = get_map_ob(op->map,x,y);tmp!=NULL;tmp=tmp->above) { 
  
!        /* And now we'd better do an inventory traversal of each
! 	* of these objects' inventory */
  
!        for(tmp2=tmp->inv;tmp2!=NULL;tmp2=tmp2->below) 
           if(tmp2->type==RUNE&&tmp2->stats.Cha<=1) {
                trap_show(tmp2,tmp);
                if(trap_disarm(op,tmp2,1))
  		   success += calc_skill_exp(op,tmp2);
           }
  
!        if(tmp->type==RUNE&&tmp->stats.Cha<=1) {
           trap_show(tmp,tmp);
           if (trap_disarm(op,tmp,1))
  		   success += calc_skill_exp(op,tmp);
---------- cut here ---------- cut here ---------- cut here ----------

I am sending this patch to the list because it significantly improves
the stability of the game, and thus it is probably useful for most of
you.  This is especially true if you have a high-level character for
which the spells and skills with large area effects have a greater
chance of reaching out of the map.

-Raphael