Qt tombstone bugs
Infrastructure bits: Qt tombstone uses a short buffer; make sure that the plname value fits instead of relying on snprintf() to truncate it. A warning about gold, if any, was iffy but this should guarantee no reason for future complaint. Year was safe but a compiler sensitive to buffer overflows wouldn't know that. Actual bugs: Qt used money in inventory for gold amount on tombstone; that overlooks gold in containers and will be 0 by tombstone stage if bones get saved. Year was recalculated from current date+time instead of using the value that gets passed in--blindly flagging that variable as UNUSED was a mistake.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.288 $ $NHDT-Date: 1597707740 2020/08/17 23:42:20 $
|
||||
NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.289 $ $NHDT-Date: 1597967807 2020/08/20 23:56:47 $
|
||||
|
||||
General Fixes and Modified Features
|
||||
-----------------------------------
|
||||
@@ -383,6 +383,12 @@ Qt: "paper doll" subset of persistent inventory has undergone several changes:
|
||||
first active light source in a previously unused slot on lower right;
|
||||
show first leash-in-use in a previously unused slot on lower left
|
||||
Qt: paper doll inventory view was inconsistently updated during Hallucination
|
||||
Qt: when hero died, gold on tombstone only included gold in inventory, not
|
||||
any additional gold inside carried containers; also, inventory gold
|
||||
will be zero if bones get created for all 3.6.x and for 3.4.x+GOLDOBJ
|
||||
Qt: tombstone showed newly constructed date instead of the value set up at
|
||||
time of death; it only shows year but that could be wrong if player
|
||||
stared at or ignored prior --More-- for long enough on 31 December
|
||||
Qt+QSX: fix control key
|
||||
Qt+OSX: rename menu entry "nethack->Preferences..." for invoking nethack's
|
||||
'O' command to "Game->Run-time options" and entry "Game->Qt settings"
|
||||
|
||||
@@ -105,7 +105,7 @@ extern void curses_number_pad(int state);
|
||||
extern void curses_delay_output(void);
|
||||
extern void curses_start_screen(void);
|
||||
extern void curses_end_screen(void);
|
||||
extern void curses_outrip(winid wid, int how);
|
||||
extern void curses_outrip(winid wid, int how, time_t when);
|
||||
extern void genl_outrip(winid tmpwin, int how, time_t when);
|
||||
extern void curses_preference_update(const char *pref);
|
||||
extern void curs_reset_windows(boolean, boolean);
|
||||
|
||||
36
src/rip.c
36
src/rip.c
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.7 rip.c $NHDT-Date: 1596498204 2020/08/03 23:43:24 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.32 $ */
|
||||
/* NetHack 3.7 rip.c $NHDT-Date: 1597967808 2020/08/20 23:56:48 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.33 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/*-Copyright (c) Robert Patrick Rankin, 2017. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
@@ -60,12 +60,10 @@ static const char *rip_txt[] = {
|
||||
};
|
||||
#define STONE_LINE_CENT 19 /* char[] element of center of stone face */
|
||||
#endif /* NH320_DEDICATION */
|
||||
#define STONE_LINE_LEN \
|
||||
16 /* # chars that fit on one line \
|
||||
* (note 1 ' ' border) \
|
||||
*/
|
||||
#define NAME_LINE 6 /* *char[] line # for player name */
|
||||
#define GOLD_LINE 7 /* *char[] line # for amount of gold */
|
||||
#define STONE_LINE_LEN 16 /* # chars that fit on one line
|
||||
* (note 1 ' ' border) */
|
||||
#define NAME_LINE 6 /* *char[] line # for player name */
|
||||
#define GOLD_LINE 7 /* *char[] line # for amount of gold */
|
||||
#define DEATH_LINE 8 /* *char[] line # for death description */
|
||||
#define YEAR_LINE 12 /* *char[] line # for year */
|
||||
|
||||
@@ -90,9 +88,9 @@ time_t when;
|
||||
register char **dp;
|
||||
register char *dpx;
|
||||
char buf[BUFSZ];
|
||||
long year;
|
||||
register int x;
|
||||
int line;
|
||||
int line, year;
|
||||
long cash;
|
||||
|
||||
g.rip = dp = (char **) alloc(sizeof(rip_txt));
|
||||
for (x = 0; rip_txt[x]; ++x)
|
||||
@@ -100,13 +98,15 @@ time_t when;
|
||||
dp[x] = (char *) 0;
|
||||
|
||||
/* Put name on stone */
|
||||
Sprintf(buf, "%s", g.plname);
|
||||
buf[STONE_LINE_LEN] = 0;
|
||||
Sprintf(buf, "%.*s", (int) STONE_LINE_LEN, g.plname);
|
||||
center(NAME_LINE, buf);
|
||||
|
||||
/* Put $ on stone */
|
||||
Sprintf(buf, "%ld Au", g.done_money);
|
||||
buf[STONE_LINE_LEN] = 0; /* It could be a *lot* of gold :-) */
|
||||
cash = max(g.done_money, 0L);
|
||||
/* arbitrary upper limit; practical upper limit is quite a bit less */
|
||||
if (cash > 999999999L)
|
||||
cash = 999999999L;
|
||||
Sprintf(buf, "%ld Au", cash);
|
||||
center(GOLD_LINE, buf);
|
||||
|
||||
/* Put together death description */
|
||||
@@ -114,11 +114,11 @@ time_t when;
|
||||
|
||||
/* Put death type on stone */
|
||||
for (line = DEATH_LINE, dpx = buf; line < YEAR_LINE; line++) {
|
||||
register int i, i0;
|
||||
char tmpchar;
|
||||
int i, i0 = (int) strlen(dpx);
|
||||
|
||||
if ((i0 = strlen(dpx)) > STONE_LINE_LEN) {
|
||||
for (i = STONE_LINE_LEN; ((i0 > STONE_LINE_LEN) && i); i--)
|
||||
if (i0 > STONE_LINE_LEN) {
|
||||
for (i = STONE_LINE_LEN; (i > 0) && (i0 > STONE_LINE_LEN); --i)
|
||||
if (dpx[i] == ' ')
|
||||
i0 = i;
|
||||
if (!i)
|
||||
@@ -135,8 +135,8 @@ time_t when;
|
||||
}
|
||||
|
||||
/* Put year on stone */
|
||||
year = yyyymmdd(when) / 10000L;
|
||||
Sprintf(buf, "%4ld", year);
|
||||
year = (int) ((yyyymmdd(when) / 10000L) % 10000L);
|
||||
Sprintf(buf, "%4d", year);
|
||||
center(YEAR_LINE, buf);
|
||||
|
||||
#ifdef DUMPLOG
|
||||
|
||||
@@ -653,7 +653,7 @@ bool NetHackQtTextWindow::Destroy()
|
||||
return !isVisible();
|
||||
}
|
||||
|
||||
void NetHackQtTextWindow::UseRIP(int how, time_t when UNUSED)
|
||||
void NetHackQtTextWindow::UseRIP(int how, time_t when)
|
||||
{
|
||||
// Code from X11 windowport
|
||||
#define STONE_LINE_LEN 16 /* # chars that fit on one line */
|
||||
@@ -677,41 +677,63 @@ static char** rip_line=0;
|
||||
int line;
|
||||
|
||||
/* Put name on stone */
|
||||
snprintf(rip_line[NAME_LINE], STONE_LINE_LEN+1, "%s", g.plname);
|
||||
(void) snprintf(rip_line[NAME_LINE], STONE_LINE_LEN + 1,
|
||||
"%.*s", STONE_LINE_LEN, g.plname);
|
||||
|
||||
/* Put $ on stone */
|
||||
snprintf(rip_line[GOLD_LINE], STONE_LINE_LEN+1, "%ld Au", money_cnt(g.invent));
|
||||
/* Put $ on stone;
|
||||
to keep things safe and relatively simple, impose an arbitrary
|
||||
upper limit that's the same for 64 bit and 32 bit configurations
|
||||
(also 16 bit configurations provided they use 32 bit long); the
|
||||
upper limit for directly carried gold is somewhat less than 300K
|
||||
due to carrying capacity, but end-of-game handling has already
|
||||
added in gold from containers, so the amount could be much more
|
||||
(simplest case: ~300K four times in a blessed bag of holding, so
|
||||
~1.2M; in addition to the hassle of getting such a thing set up,
|
||||
it would need many gold-rich bones levels or wizard mode wishing) */
|
||||
long cash = std::max(g.done_money, 0L);
|
||||
/* force less that 10 digits to satisfy elaborate format checking;
|
||||
it's arbitrary but still way, way more than could ever be needed */
|
||||
if (cash > 999999999L)
|
||||
cash = 999999999L;
|
||||
(void) snprintf(rip_line[GOLD_LINE], STONE_LINE_LEN + 1, "%ld Au", cash);
|
||||
|
||||
/* Put together death description */
|
||||
formatkiller(buf, sizeof buf, how, FALSE);
|
||||
//str_copy(buf, killer, SIZE(buf));
|
||||
|
||||
/* Put death type on stone */
|
||||
for (line=DEATH_LINE, dpx = buf; line<YEAR_LINE; line++) {
|
||||
int i,i0;
|
||||
for (line = DEATH_LINE, dpx = buf; line < YEAR_LINE; ++line) {
|
||||
char tmpchar;
|
||||
int i, i0 = (int) strlen(dpx);
|
||||
|
||||
if ( (i0=strlen(dpx)) > STONE_LINE_LEN) {
|
||||
for(i = STONE_LINE_LEN;
|
||||
((i0 > STONE_LINE_LEN) && i); i--)
|
||||
if(dpx[i] == ' ') i0 = i;
|
||||
if(!i) i0 = STONE_LINE_LEN;
|
||||
if (i0 > STONE_LINE_LEN) {
|
||||
for (i = STONE_LINE_LEN; (i > 0) && (i0 > STONE_LINE_LEN); --i)
|
||||
if (dpx[i] == ' ')
|
||||
i0 = i;
|
||||
if (!i)
|
||||
i0 = STONE_LINE_LEN;
|
||||
}
|
||||
tmpchar = dpx[i0];
|
||||
dpx[i0] = 0;
|
||||
str_copy(rip_line[line], dpx, STONE_LINE_LEN+1);
|
||||
(void) str_copy(rip_line[line], dpx, STONE_LINE_LEN + 1);
|
||||
if (tmpchar != ' ') {
|
||||
dpx[i0] = tmpchar;
|
||||
dpx= &dpx[i0];
|
||||
} else dpx= &dpx[i0+1];
|
||||
} else {
|
||||
dpx= &dpx[i0 + 1];
|
||||
}
|
||||
}
|
||||
|
||||
/* Put year on stone */
|
||||
snprintf(rip_line[YEAR_LINE], STONE_LINE_LEN+1, "%4d", getyear());
|
||||
/* Put year on stone;
|
||||
64 bit configuration with 64 bit int is capable of overflowing
|
||||
STONE_LINE_LEN characters; a compiler might warn about that,
|
||||
so force a value that it can recognize as fitting within buffer's
|
||||
range ("%4d" imposes a minimum number of digits, not a maximum) */
|
||||
int year = (int) ((yyyymmdd(when) / 10000L) % 10000L); /* Y10K bug! */
|
||||
(void) snprintf(rip_line[YEAR_LINE], STONE_LINE_LEN + 1, "%4d", year);
|
||||
|
||||
rip.setLines(rip_line,YEAR_LINE+1);
|
||||
|
||||
use_rip=true;
|
||||
rip.setLines(rip_line, YEAR_LINE + 1);
|
||||
use_rip = true;
|
||||
}
|
||||
|
||||
void NetHackQtTextWindow::Clear()
|
||||
@@ -820,8 +842,9 @@ void NetHackQtMenuOrTextWindow::StartMenu()
|
||||
if (!actual) actual=new NetHackQtMenuWindow(parent);
|
||||
actual->StartMenu();
|
||||
}
|
||||
void NetHackQtMenuOrTextWindow::AddMenu(int glyph, const ANY_P* identifier, char ch, char gch, int attr,
|
||||
const QString& str, unsigned itemflags)
|
||||
void NetHackQtMenuOrTextWindow::AddMenu(int glyph, const ANY_P* identifier,
|
||||
char ch, char gch, int attr,
|
||||
const QString& str, unsigned itemflags)
|
||||
{
|
||||
if (!actual) impossible("AddMenu called before we know if Menu or Text");
|
||||
actual->AddMenu(glyph,identifier,ch,gch,attr,str,itemflags);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.7 wintext.c $NHDT-Date: 1596498376 2020/08/03 23:46:16 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.21 $ */
|
||||
/* NetHack 3.7 wintext.c $NHDT-Date: 1597967808 2020/08/20 23:56:48 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.22 $ */
|
||||
/* Copyright (c) Dean Luick, 1992 */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -489,14 +489,20 @@ calculate_rip_text(int how, time_t when)
|
||||
|
||||
char buf[BUFSZ];
|
||||
char *dpx;
|
||||
int line;
|
||||
long year;
|
||||
int line, year;
|
||||
long cash;
|
||||
|
||||
/* Put name on stone */
|
||||
Sprintf(rip_line[NAME_LINE], "%s", g.plname);
|
||||
|
||||
/* Put $ on stone */
|
||||
Sprintf(rip_line[GOLD_LINE], "%ld Au", g.done_money);
|
||||
cash = max(g.done_money, 0L);
|
||||
/* arbitrary upper limit; practical upper limit is quite a bit less */
|
||||
if (cash > 999999999L)
|
||||
cash = 999999999L;
|
||||
Sprintf(buf, "%ld Au", cash);
|
||||
Sprintf(rip_line[GOLD_LINE], "%ld Au", cash);
|
||||
|
||||
/* Put together death description */
|
||||
formatkiller(buf, sizeof buf, how, FALSE);
|
||||
|
||||
@@ -523,8 +529,8 @@ calculate_rip_text(int how, time_t when)
|
||||
}
|
||||
|
||||
/* Put year on stone */
|
||||
year = yyyymmdd(when) / 10000L;
|
||||
Sprintf(rip_line[YEAR_LINE], "%4ld", year);
|
||||
year = (int) ((yyyymmdd(when) / 10000L) % 10000L);
|
||||
Sprintf(rip_line[YEAR_LINE], "%4d", year);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -898,12 +898,13 @@ curses_end_screen()
|
||||
|
||||
/*
|
||||
outrip(winid, int)
|
||||
-- The tombstone code. If you want the traditional code use
|
||||
genl_outrip for the value and check the #if in rip.c.
|
||||
-- The tombstone code. We use genl_outrip() from rip.c
|
||||
instead of rolling our own.
|
||||
*/
|
||||
void
|
||||
curses_outrip(winid wid UNUSED,
|
||||
int how UNUSED)
|
||||
int how UNUSED,
|
||||
time_t when UNUSED)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user