[comp.sources.games.bugs] bug in nethack3.0.4

mac@ardent.com (10/10/89)

	A rust monster was chewing up my hard shoes, so I took them
off; to see: Segmentation fault (core dumped)

	It seems that in Boots_off(), unlike all the other Item_off()
routines, setworn((item *)0,item_class) gets called before the switch
statement that prints the cute message or whatever.  
	There is a comment that says this is to support the Levitation
boots, which end up returning from float_down() or some such.  Well,
it seems that setworn reaches in and effectivly undefines *uarmf,
which even though another copy was made (into *obj), since the target
gets zero'ed, all pointers to dereference to zero. Hence seg fault;
Hence the following patch:

[Note: I could have just cached obj->otyp, but was not sure what other
 routine might need obj or uarmf]

[Note 2: This occurred on an Ardent Titan, which might have been a bit
 more ambitious than other machines at optimization; however, the code
 to me looks to be broken...]
	
*** do_wear.c.old	Mon Oct  9 22:45:31 1989
--- do_wear.c	Mon Oct  9 22:49:33 1989
***************
*** 116,126 ****
      register struct obj *obj = uarmf;
  	/* For levitation, float_down() returns if Levitation, so we
  	 * must do a setworn() _before_ the levitation case.
  	 */
      long oldprop =
  		u.uprops[objects[uarmf->otyp].oc_oprop].p_flgs & ~(WORN_BOOTS | TIMEOUT);
  
-     setworn((struct obj *)0, W_ARMF);
      switch(obj->otyp) {
  	case SPEED_BOOTS:
  		if (!oldprop) {
--- 116,128 ----
      register struct obj *obj = uarmf;
  	/* For levitation, float_down() returns if Levitation, so we
  	 * must do a setworn() _before_ the levitation case.
+ 	 * mac@ardent: however, setworn cannot be called until
+          * after the switch statement, as it alters uarmf, which is obj...
+          * hence if Lev, call there, else at end. 
  	 */
      long oldprop =
  		u.uprops[objects[uarmf->otyp].oc_oprop].p_flgs & ~(WORN_BOOTS | TIMEOUT);
  
      switch(obj->otyp) {
  	case SPEED_BOOTS:
  		if (!oldprop) {
***************
*** 151,156 ****
--- 153,160 ----
  		break;
  	case LEVITATION_BOOTS:
  		if (!oldprop) {
+ 			/* Fix by mac@ardent 10/9/89 */
+ 		        setworn((struct obj *)0, W_ARMF);
  			(void) float_down();
  			makeknown(obj->otyp);
  		}
***************
*** 162,167 ****
--- 166,173 ----
  		break;
  	default: impossible("Unknown type of boots (%d)", obj->otyp);
      }
+ /* Fix by mac@ardent 10/9/89 */
+     setworn((struct obj *)0, W_ARMF);
      return 0;
  }
  

mac@ardent.com
[sorry for posting a copy of this to r.g.h; it looks so bad there what with
the current discussion about how bugs should go here, hints/games
discussions there.... Oh well.]