fix "object lost" panic after query_objlist

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.
This commit is contained in:
PatR
2016-03-20 13:01:56 -07:00
parent c53565036c
commit 3353ad1114
2 changed files with 13 additions and 11 deletions
+1
View 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 an alternate message instead of prohibiting the promotion
kicked weapon which successfully hits monster vanishes from play kicked weapon which successfully hits monster vanishes from play
unseen landmine explosion could result in "The <monst-type> statue crumbles." 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 Platform- and/or Interface-Specific Fixes
+12 -11
View File
@@ -464,7 +464,7 @@ int what; /* should be a long */
int i, n, res, count, n_tried = 0, n_picked = 0; int i, n, res, count, n_tried = 0, n_picked = 0;
menu_item *pick_list = (menu_item *) 0; menu_item *pick_list = (menu_item *) 0;
boolean autopickup = what > 0; boolean autopickup = what > 0;
struct obj *objchain; struct obj **objchain_p;
int traverse_how; int traverse_how;
/* we might have arrived here while fainted or sleeping, via /* 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 */ add_valid_menu_class(0); /* reset */
if (!u.uswallow) { if (!u.uswallow) {
objchain = level.objects[u.ux][u.uy]; objchain_p = &level.objects[u.ux][u.uy];
traverse_how = BY_NEXTHERE; traverse_how = BY_NEXTHERE;
} else { } else {
objchain = u.ustuck->minvent; objchain_p = &u.ustuck->minvent;
traverse_how = 0; /* nobj */ traverse_how = 0; /* nobj */
} }
/* /*
@@ -535,7 +535,7 @@ int what; /* should be a long */
* to make things less confusing. * to make things less confusing.
*/ */
if (autopickup) { if (autopickup) {
n = autopick(objchain, traverse_how, &pick_list); n = autopick(*objchain_p, traverse_how, &pick_list);
goto menu_pickup; goto menu_pickup;
} }
@@ -547,16 +547,17 @@ int what; /* should be a long */
Sprintf(qbuf, "Pick %d of what?", count); Sprintf(qbuf, "Pick %d of what?", count);
val_for_n_or_more = count; /* set up callback selector */ 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); &pick_list, PICK_ONE, n_or_more);
/* correct counts, if any given */ /* correct counts, if any given */
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
pick_list[i].count = count; pick_list[i].count = count;
} else { } else {
n = query_objlist("Pick up what?", &objchain, n = query_objlist("Pick up what?", objchain_p,
(traverse_how | FEEL_COCKATRICE), (traverse_how | FEEL_COCKATRICE),
&pick_list, PICK_ANY, all_but_uchain); &pick_list, PICK_ANY, all_but_uchain);
} }
menu_pickup: menu_pickup:
n_tried = n; n_tried = n;
for (n_picked = i = 0; i < n; i++) { for (n_picked = i = 0; i < n; i++) {
@@ -582,12 +583,12 @@ int what; /* should be a long */
selective = FALSE; /* ask for each item */ selective = FALSE; /* ask for each item */
/* check for more than one object */ /* 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++; ct++;
if (ct == 1 && count) { if (ct == 1 && count) {
/* if only one thing, then pick it */ /* if only one thing, then pick it */
obj = objchain; obj = *objchain_p;
lcount = min(obj->quan, (long) count); lcount = min(obj->quan, (long) count);
n_tried++; n_tried++;
if (pickup_object(obj, lcount, FALSE) > 0) 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"); There("are %s objects here.", (ct <= 10) ? "several" : "many");
if (!query_classes(oclasses, &selective, &all_of_a_type, if (!query_classes(oclasses, &selective, &all_of_a_type,
"pick up", objchain, "pick up", *objchain_p,
(traverse_how & BY_NEXTHERE) ? TRUE : FALSE, (traverse_how & BY_NEXTHERE) ? TRUE : FALSE,
&via_menu)) { &via_menu)) {
if (!via_menu) if (!via_menu)
return 0; return 0;
if (selective) if (selective)
traverse_how |= INVORDER_SORT; 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, &pick_list, PICK_ANY,
(via_menu == -2) ? allow_all (via_menu == -2) ? allow_all
: allow_category); : 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); obj2 = FOLLOW(obj, traverse_how);
if (!selective && oclasses[0] && !index(oclasses, obj->oclass)) if (!selective && oclasses[0] && !index(oclasses, obj->oclass))
continue; continue;