mdlib.c revisited

There is a slight change in behavior here when collecting build-time
option information.  If MAXOPT is too small, collecting will now save
MAXOPT lines and then skip anything that should come after.  It used
to always keep the very last line, each time replacing whatever the
previous last line was, but would leak memory if that ever happened.
And after yesterday's "fix" it would try to keep that very last line
beyond the array bounds.
This commit is contained in:
PatR
2023-12-08 19:12:38 -08:00
parent cb1eadd6b7
commit 0c88c91c83

View File

@@ -95,6 +95,10 @@ static void build_savebones_compat_string(void);
static int idxopttext, done_runtime_opt_init_once = 0; static int idxopttext, done_runtime_opt_init_once = 0;
#define MAXOPT 60 /* 3.7: currently 40 lines get inserted into opttext[] */ #define MAXOPT 60 /* 3.7: currently 40 lines get inserted into opttext[] */
static char *opttext[MAXOPT] = { 0 }; static char *opttext[MAXOPT] = { 0 };
#define STOREOPTTEXT(line) \
((void) ((idxopttext < MAXOPT) \
? (opttext[idxopttext++] = dupstr(line)) \
: 0))
char optbuf[COLBUFSZ]; char optbuf[COLBUFSZ];
static struct version_info version; static struct version_info version;
static const char opt_indent[] = " "; static const char opt_indent[] = " ";
@@ -735,9 +739,7 @@ opt_out_words(
if (word) if (word)
*word = '\0'; *word = '\0';
if (*length_p + (int) strlen(str) > COLNO - 5) { if (*length_p + (int) strlen(str) > COLNO - 5) {
opttext[idxopttext] = dupstr(optbuf); STOREOPTTEXT(optbuf);
if (idxopttext < MAXOPT)
idxopttext++;
Sprintf(optbuf, "%s", opt_indent), Sprintf(optbuf, "%s", opt_indent),
*length_p = (int) strlen(opt_indent); *length_p = (int) strlen(opt_indent);
} else { } else {
@@ -762,9 +764,7 @@ build_options(void)
#endif #endif
#endif #endif
build_savebones_compat_string(); build_savebones_compat_string();
opttext[idxopttext] = dupstr(optbuf); STOREOPTTEXT(optbuf);
if (idxopttext < MAXOPT)
idxopttext++;
#if (NH_DEVEL_STATUS != NH_STATUS_RELEASED) #if (NH_DEVEL_STATUS != NH_STATUS_RELEASED)
#if (NH_DEVEL_STATUS == NH_STATUS_BETA) #if (NH_DEVEL_STATUS == NH_STATUS_BETA)
#define STATUS_ARG " [beta]" #define STATUS_ARG " [beta]"
@@ -776,13 +776,9 @@ build_options(void)
#endif /* NH_DEVEL_STATUS == NH_STATUS_RELEASED */ #endif /* NH_DEVEL_STATUS == NH_STATUS_RELEASED */
Sprintf(optbuf, "%sNetHack version %d.%d.%d%s\n", Sprintf(optbuf, "%sNetHack version %d.%d.%d%s\n",
opt_indent, VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL, STATUS_ARG); opt_indent, VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL, STATUS_ARG);
opttext[idxopttext] = dupstr(optbuf); STOREOPTTEXT(optbuf);
if (idxopttext < MAXOPT)
idxopttext++;
Sprintf(optbuf, "Options compiled into this edition:"); Sprintf(optbuf, "Options compiled into this edition:");
opttext[idxopttext] = dupstr(optbuf); STOREOPTTEXT(optbuf);
if (idxopttext < MAXOPT)
idxopttext++;
optbuf[0] = '\0'; optbuf[0] = '\0';
length = COLNO + 1; /* force 1st item onto new line */ length = COLNO + 1; /* force 1st item onto new line */
for (i = 0; i < SIZE(build_opts); i++) { for (i = 0; i < SIZE(build_opts); i++) {
@@ -798,19 +794,13 @@ build_options(void)
(i < SIZE(build_opts) - 1) ? "," : "."); (i < SIZE(build_opts) - 1) ? "," : ".");
opt_out_words(buf, &length); opt_out_words(buf, &length);
} }
opttext[idxopttext] = dupstr(optbuf); STOREOPTTEXT(optbuf);
if (idxopttext < MAXOPT)
idxopttext++;
optbuf[0] = '\0'; optbuf[0] = '\0';
winsyscnt = count_and_validate_winopts(); winsyscnt = count_and_validate_winopts();
opttext[idxopttext] = dupstr(optbuf); STOREOPTTEXT(optbuf);
if (idxopttext < MAXOPT)
idxopttext++;
Sprintf(optbuf, "Supported windowing system%s:", Sprintf(optbuf, "Supported windowing system%s:",
(winsyscnt > 1) ? "s" : ""); (winsyscnt > 1) ? "s" : "");
opttext[idxopttext] = dupstr(optbuf); STOREOPTTEXT(optbuf);
if (idxopttext < MAXOPT)
idxopttext++;
optbuf[0] = '\0'; optbuf[0] = '\0';
length = COLNO + 1; /* force 1st item onto new line */ length = COLNO + 1; /* force 1st item onto new line */
@@ -842,19 +832,12 @@ build_options(void)
#if !defined(MAKEDEFS_C) #if !defined(MAKEDEFS_C)
cnt = 0; cnt = 0;
opttext[idxopttext] = dupstr(optbuf); STOREOPTTEXT(optbuf);
if (idxopttext < MAXOPT)
idxopttext++;
optbuf[0] = '\0'; optbuf[0] = '\0';
soundlibcnt = count_and_validate_soundlibopts(); soundlibcnt = count_and_validate_soundlibopts();
opttext[idxopttext] = dupstr(optbuf); STOREOPTTEXT(optbuf);
if (idxopttext < MAXOPT) Sprintf(optbuf, "Supported soundlib%s:", (soundlibcnt > 1) ? "s" : "");
idxopttext++; STOREOPTTEXT(optbuf);
Sprintf(optbuf, "Supported soundlib%s:",
(soundlibcnt > 1) ? "s" : "");
opttext[idxopttext] = dupstr(optbuf);
if (idxopttext < MAXOPT)
idxopttext++;
optbuf[0] = '\0'; optbuf[0] = '\0';
length = COLNO + 1; /* force 1st item onto new line */ length = COLNO + 1; /* force 1st item onto new line */
@@ -892,9 +875,7 @@ build_options(void)
#endif #endif
#endif /* !MAKEDEFS_C */ #endif /* !MAKEDEFS_C */
opttext[idxopttext] = dupstr(optbuf); STOREOPTTEXT(optbuf);
if (idxopttext < MAXOPT)
idxopttext++;
optbuf[0] = '\0'; optbuf[0] = '\0';
#if defined(MAKEDEFS_C) || defined(FOR_RUNTIME) #if defined(MAKEDEFS_C) || defined(FOR_RUNTIME)
@@ -920,21 +901,18 @@ build_options(void)
/* add lua copyright notice; /* add lua copyright notice;
":TAG:" substitutions are deferred to caller */ ":TAG:" substitutions are deferred to caller */
for (i = 0; lua_info[i]; ++i) { for (i = 0; lua_info[i]; ++i) {
opttext[idxopttext] = dupstr(lua_info[i]); STOREOPTTEXT(lua_info[i]);
if (idxopttext < MAXOPT)
idxopttext++;
} }
} }
#endif /* MAKEDEFS_C || FOR_RUNTIME */ #endif /* MAKEDEFS_C || FOR_RUNTIME */
/* end with a blank line */ /* end with a blank line */
opttext[idxopttext] = dupstr(""); STOREOPTTEXT("");
if (idxopttext < MAXOPT)
idxopttext++;
opttext[MAXOPT - 1] = NULL;
return; return;
} }
#undef STOREOPTTEXT
int int
case_insensitive_comp(const char *s1, const char *s2) case_insensitive_comp(const char *s1, const char *s2)
{ {