From: PatR Date: Sun, 20 Mar 2016 20:01:56 +0000 (-0700) Subject: fix "object lost" panic after query_objlist X-Git-Tag: NetHack-3.6.1_RC01~862 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3353ad11147045cc2351ea22aa5eb2c7357e4ac9;p=nethack 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. --- diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 815ef5f5e..ee41c08b2 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -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 statue crumbles." +post-3.6.0: fix "object lost" panic during pickup caused by sortloot revamp Platform- and/or Interface-Specific Fixes diff --git a/src/pickup.c b/src/pickup.c index 466c1e10f..368508b16 100644 --- a/src/pickup.c +++ b/src/pickup.c @@ -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;