From 7c860335c16bfb8382eab4b75ebd01dbd1a69120 Mon Sep 17 00:00:00 2001 From: "nethack.rankin" Date: Thu, 1 Nov 2007 19:24:19 +0000 Subject: [PATCH] 0 gold pieces (trunk only) Newsgroup discussion about the devnull tournament which started today has pointed out that ``d4294967296$'' would cause getobj() to create a gold piece object with quantity 0 which then got dropped to the floor. (It's specific to gold; other types of objects don't behave that way.) Also, wrapping which went past negative and zero all the way to positive again (like 429496729*10+7, yielding 1) wasn't detected. --- doc/fixes35.0 | 1 + src/invent.c | 48 ++++++++++++++++++++++++++++++------------------ 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/doc/fixes35.0 b/doc/fixes35.0 index 70dfff8a9..83c8e3a92 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -267,6 +267,7 @@ tin contents can now sometimes be accessed on the same turn that the tin starts being opened; when not, the opening feedback is more accurate Nth adjustment of feedback when observing a pet eating monsters who want the Amulet won't attack temple priests to try to get it +it was possible to generate an object of 0 gold pieces by dropping 2**32 gold Platform- and/or Interface-Specific Fixes diff --git a/src/invent.c b/src/invent.c index 0600b9841..4b3877945 100644 --- a/src/invent.c +++ b/src/invent.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)invent.c 3.5 2007/06/04 */ +/* SCCS Id: @(#)invent.c 3.5 2007/11/01 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -828,8 +828,8 @@ register const char *let,*word; boolean allownone = FALSE; boolean useboulder = FALSE; xchar foox = 0; - long cnt; - boolean prezero = FALSE; + long cnt, prevcnt; + boolean prezero; long dummymask; if(*let == ALLOW_COUNT) let++, allowcnt = 1; @@ -1023,6 +1023,7 @@ register const char *let,*word; for(;;) { cnt = 0; if (allowcnt == 2) allowcnt = 1; /* abort previous count */ + prezero = FALSE; if(!buf[0]) { Sprintf(qbuf, "What do you want to %s? [*]", word); } else { @@ -1035,18 +1036,28 @@ register const char *let,*word; else #endif ilet = yn_function(qbuf, (char *)0, '\0'); - if(ilet == '0') prezero = TRUE; - while(digit(ilet) && allowcnt) { -#ifdef REDO - if (ilet != '?' && ilet != '*') savech(ilet); -#endif - cnt = 10*cnt + (ilet - '0'); - allowcnt = 2; /* signal presence of cnt */ - ilet = readchar(); + if (digit(ilet) && !allowcnt) { + pline("No count allowed with this command."); + continue; } - if(digit(ilet)) { - pline("No count allowed with this command."); - continue; + if (ilet == '0') prezero = TRUE; + while (digit(ilet)) { +#ifdef REDO + if (ilet != '?' && ilet != '*') savech(ilet); +#endif + /* accumulate unless cnt has overflowed */ + if (allowcnt < 3) { + prevcnt = cnt; + cnt = 10L * cnt + (long)(ilet - '0'); + /* signal presence of cnt */ + allowcnt = (cnt >= prevcnt) ? 2 : 3; + } + ilet = readchar(); + } + if (allowcnt == 3) { + /* overflow detected; force cnt to be invalid */ + cnt = -1L; + allowcnt = 2; } if(index(quitchars,ilet)) { if(flags.verbose) @@ -1066,16 +1077,17 @@ register const char *let,*word; return(struct obj *)0; #endif } - if(cnt == 0 && prezero) return((struct obj *)0); /* Historic note: early Nethack had a bug which was * first reported for Larn, where trying to drop 2^32-n * gold pieces was allowed, and did interesting things * to your money supply. The LRS is the tax bureau * from Larn. */ - if(cnt < 0) { - pline_The("LRS would be very interested to know you have that much."); - return(struct obj *)0; + if (cnt <= 0) { + if (cnt < 0 || !prezero) + pline_The( + "LRS would be very interested to know you have that much."); + return (struct obj *)0; } #ifndef GOLDOBJ