]> granicus.if.org Git - nethack/commitdiff
fix "object lost" panic after query_objlist
authorPatR <rankin@nethack.org>
Sun, 20 Mar 2016 20:01:56 +0000 (13:01 -0700)
committerPatR <rankin@nethack.org>
Sun, 20 Mar 2016 20:01:56 +0000 (13:01 -0700)
Reported directly to devteam for recent git code, the "sortloot
revamp" patch could trigger an object lost panic after calling
query_objlist() when menustyle was full or partial and player
picked up a subset of available items.  Modified head-of-list was
not being propagated to its source in pickup().  Use an extra layer
of indirection.

doc/fixes36.1
src/pickup.c

index 815ef5f5e21111df0dfa41fa2198ec9c2aaf5484..ee41c08b20228567b2d1f6dd50ba159173d552a6 100644 (file)
@@ -192,6 +192,7 @@ female gnome who gains level can grow up into male-only gnome lord; give an
        an alternate message instead of prohibiting the promotion
 kicked weapon which successfully hits monster vanishes from play
 unseen landmine explosion could result in "The <monst-type> statue crumbles."
+post-3.6.0: fix "object lost" panic during pickup caused by sortloot revamp
 
 
 Platform- and/or Interface-Specific Fixes
index 466c1e10f335f3d28af9de244adc1013ee3805f1..368508b16d4b16b6109e8e9fa5af8a9a9e327be3 100644 (file)
@@ -464,7 +464,7 @@ int what; /* should be a long */
     int i, n, res, count, n_tried = 0, n_picked = 0;
     menu_item *pick_list = (menu_item *) 0;
     boolean autopickup = what > 0;
-    struct obj *objchain;
+    struct obj **objchain_p;
     int traverse_how;
 
     /* we might have arrived here while fainted or sleeping, via
@@ -522,10 +522,10 @@ int what; /* should be a long */
 
     add_valid_menu_class(0); /* reset */
     if (!u.uswallow) {
-        objchain = level.objects[u.ux][u.uy];
+        objchain_p = &level.objects[u.ux][u.uy];
         traverse_how = BY_NEXTHERE;
     } else {
-        objchain = u.ustuck->minvent;
+        objchain_p = &u.ustuck->minvent;
         traverse_how = 0; /* nobj */
     }
     /*
@@ -535,7 +535,7 @@ int what; /* should be a long */
      * to make things less confusing.
      */
     if (autopickup) {
-        n = autopick(objchain, traverse_how, &pick_list);
+        n = autopick(*objchain_p, traverse_how, &pick_list);
         goto menu_pickup;
     }
 
@@ -547,16 +547,17 @@ int what; /* should be a long */
 
             Sprintf(qbuf, "Pick %d of what?", count);
             val_for_n_or_more = count; /* set up callback selector */
-            n = query_objlist(qbuf, &objchain, traverse_how,
+            n = query_objlist(qbuf, objchain_p, traverse_how,
                               &pick_list, PICK_ONE, n_or_more);
             /* correct counts, if any given */
             for (i = 0; i < n; i++)
                 pick_list[i].count = count;
         } else {
-            n = query_objlist("Pick up what?", &objchain,
+            n = query_objlist("Pick up what?", objchain_p,
                               (traverse_how | FEEL_COCKATRICE),
                               &pick_list, PICK_ANY, all_but_uchain);
         }
+
     menu_pickup:
         n_tried = n;
         for (n_picked = i = 0; i < n; i++) {
@@ -582,12 +583,12 @@ int what; /* should be a long */
         selective = FALSE;    /* ask for each item */
 
         /* check for more than one object */
-        for (obj = objchain; obj; obj = FOLLOW(obj, traverse_how))
+        for (obj = *objchain_p; obj; obj = FOLLOW(obj, traverse_how))
             ct++;
 
         if (ct == 1 && count) {
             /* if only one thing, then pick it */
-            obj = objchain;
+            obj = *objchain_p;
             lcount = min(obj->quan, (long) count);
             n_tried++;
             if (pickup_object(obj, lcount, FALSE) > 0)
@@ -599,14 +600,14 @@ int what; /* should be a long */
 
             There("are %s objects here.", (ct <= 10) ? "several" : "many");
             if (!query_classes(oclasses, &selective, &all_of_a_type,
-                               "pick up", objchain,
+                               "pick up", *objchain_p,
                                (traverse_how & BY_NEXTHERE) ? TRUE : FALSE,
                                &via_menu)) {
                 if (!via_menu)
                     return 0;
                 if (selective)
                     traverse_how |= INVORDER_SORT;
-                n = query_objlist("Pick up what?", &objchain, traverse_how,
+                n = query_objlist("Pick up what?", objchain_p, traverse_how,
                                   &pick_list, PICK_ANY,
                                   (via_menu == -2) ? allow_all
                                                    : allow_category);
@@ -614,7 +615,7 @@ int what; /* should be a long */
             }
         }
 
-        for (obj = objchain; obj; obj = obj2) {
+        for (obj = *objchain_p; obj; obj = obj2) {
             obj2 = FOLLOW(obj, traverse_how);
             if (!selective && oclasses[0] && !index(oclasses, obj->oclass))
                 continue;