improved regexp handling

If regex_compile() fails, free the regexp before doing anything else
in case failure reason is "out of memory".  Feedback to the user is
highly likely to panic or crash after memory runs out; this should
let the regex failure message be issued and the game continue.

User sound regular expressions were never freed.  This frees them
when FREE_ALL_MEMORY is enabled.
This commit is contained in:
PatR
2020-05-23 12:51:01 -07:00
parent 1d7ee022e6
commit 298331fe04
5 changed files with 91 additions and 41 deletions

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 extern.h $NHDT-Date: 1588798973 2020/05/06 21:02:53 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.842 $ */
/* NetHack 3.6 extern.h $NHDT-Date: 1590263447 2020/05/23 19:50:47 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.843 $ */
/* Copyright (c) Steve Creps, 1988. */
/* NetHack may be freely redistributed. See license for details. */
@@ -2459,6 +2459,7 @@ E int NDECL(tiphat);
#ifdef USER_SOUNDS
E int FDECL(add_sound_mapping, (const char *));
E void FDECL(play_sound_for_message, (const char *));
E void NDECL(release_sound_mappings);
#endif
/* ### sp_lev.c ### */

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 files.c $NHDT-Date: 1589580856 2020/05/15 22:14:16 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.313 $ */
/* NetHack 3.7 files.c $NHDT-Date: 1590263451 2020/05/23 19:50:51 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.314 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Derek S. Ray, 2015. */
/* NetHack may be freely redistributed. See license for details. */
@@ -120,7 +120,7 @@ extern char *FDECL(translate_path_variables, (const char *, char *));
#endif
#ifdef USER_SOUNDS
extern char *sounddir;
extern char *sounddir; /* defined in sounds.c */
#endif
#if defined(UNIX) && defined(QT_GRAPHICS)
@@ -2885,6 +2885,8 @@ char *origbuf;
#endif /*AMIGA*/
#ifdef USER_SOUNDS
} else if (match_varname(buf, "SOUNDDIR", 8)) {
if (sounddir)
free((genericptr_t) sounddir);
sounddir = dupstr(bufp);
} else if (match_varname(buf, "SOUND", 5)) {
add_sound_mapping(bufp);

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 options.c $NHDT-Date: 1589326675 2020/05/12 23:37:55 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.464 $ */
/* NetHack 3.7 options.c $NHDT-Date: 1590263453 2020/05/23 19:50:53 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.465 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Michael Allison, 2008. */
/* NetHack may be freely redistributed. See license for details. */
@@ -5447,7 +5447,7 @@ handler_menu_colors(VOID_ARGS)
if (*mcbuf == '\033')
goto menucolors_done;
if (*mcbuf
&& test_regex_pattern(mcbuf, (const char *)0)
&& test_regex_pattern(mcbuf, "MENUCOLORS regex")
&& (mcclr = query_color((char *) 0)) != -1
&& (mcattr = query_attr((char *) 0)) != -1
&& !add_menu_coloring_parsed(mcbuf, mcclr, mcattr)) {
@@ -5529,7 +5529,7 @@ handler_msgtype(VOID_ARGS)
if (*mtbuf == '\033')
return TRUE;
if (*mtbuf
&& test_regex_pattern(mtbuf, (const char *)0)
&& test_regex_pattern(mtbuf, "MSGTYPE regex")
&& (mttyp = query_msgtype()) != -1
&& !msgtype_add(mttyp, mtbuf)) {
pline("Error adding the message type.");
@@ -6671,16 +6671,20 @@ msgtype_add(typ, pattern)
int typ;
char *pattern;
{
static const char *re_error = "MSGTYPE regex error";
struct plinemsg_type *tmp = (struct plinemsg_type *) alloc(sizeof *tmp);
tmp->msgtype = typ;
tmp->regex = regex_init();
/* test_regex_pattern() has already validated this regexp but parsing
it again could conceivably run out of memory */
if (!regex_compile(pattern, tmp->regex)) {
static const char *re_error = "MSGTYPE regex error";
const char *re_error_desc = regex_error_desc(tmp->regex);
config_error_add("%s: %s", re_error, regex_error_desc(tmp->regex));
/* free first in case reason for failure was insufficient memory */
regex_free(tmp->regex);
free((genericptr_t) tmp);
config_error_add("%s: %s", re_error, re_error_desc);
return FALSE;
}
tmp->pattern = dupstr(pattern);
@@ -6805,30 +6809,40 @@ char *str;
return FALSE;
}
/* parse 'str' as a regular expression to check whether it's valid;
compiled regexp gets thrown away regardless of the outcome */
static boolean
test_regex_pattern(str, errmsg)
const char *str;
const char *errmsg;
{
static const char re_error[] = "Regex error";
static const char def_errmsg[] = "NHregex error";
struct nhregex *match;
boolean retval = TRUE;
const char *re_error_desc;
boolean retval;
if (!str)
return FALSE;
if (!errmsg)
errmsg = def_errmsg;
match = regex_init();
if (!match) {
config_error_add("NHregex error");
config_error_add("%s", errmsg);
return FALSE;
}
if (!regex_compile(str, match)) {
config_error_add("%s: %s", errmsg ? errmsg : re_error,
regex_error_desc(match));
retval = FALSE;
}
retval = regex_compile(str, match);
/* get potential error message before freeing regexp and free regexp
before issuing message in case the error is "ran out of memory"
since message delivery might need to allocate some memory */
re_error_desc = !retval ? regex_error_desc(match) : 0;
/* discard regexp; caller will re-parse it after validating other stuff */
regex_free(match);
/* if returning failure, tell player */
if (!retval)
config_error_add("%s: %s", errmsg, re_error_desc);
return retval;
}
@@ -6844,19 +6858,23 @@ int c, a;
return FALSE;
tmp = (struct menucoloring *) alloc(sizeof *tmp);
tmp->match = regex_init();
/* test_regex_pattern() has already validated this regexp but parsing
it again could conceivably run out of memory */
if (!regex_compile(str, tmp->match)) {
config_error_add("%s: %s", re_error, regex_error_desc(tmp->match));
const char *re_error_desc = regex_error_desc(tmp->match);
/* free first in case reason for regcomp failure was out-of-memory */
regex_free(tmp->match);
free(tmp);
free((genericptr_t) tmp);
config_error_add("%s: %s", re_error, re_error_desc);
return FALSE;
} else {
tmp->next = g.menu_colorings;
tmp->origstr = dupstr(str);
tmp->color = c;
tmp->attr = a;
g.menu_colorings = tmp;
return TRUE;
}
tmp->next = g.menu_colorings;
tmp->origstr = dupstr(str);
tmp->color = c;
tmp->attr = a;
g.menu_colorings = tmp;
return TRUE;
}
/* parse '"regex_string"=color&attr' and add it to menucoloring */
@@ -6935,6 +6953,7 @@ free_menu_coloring()
free((genericptr_t) tmp->origstr);
free((genericptr_t) tmp);
}
g.menu_colorings = (struct menucoloring *) 0;
}
static void
@@ -7752,13 +7771,14 @@ const char *mapping;
ape = (struct autopickup_exception *) alloc(sizeof *ape);
ape->regex = regex_init();
if (!regex_compile(text, ape->regex)) {
config_error_add("%s: %s", APE_regex_error,
regex_error_desc(ape->regex));
const char *re_error_desc = regex_error_desc(ape->regex);
/* free first in case reason for failure was insufficient memory */
regex_free(ape->regex);
free((genericptr_t) ape);
config_error_add("%s: %s", APE_regex_error, re_error_desc);
return 0;
}
ape->pattern = dupstr(text);
ape->grab = grab;
ape->next = g.apelist;
@@ -7796,10 +7816,10 @@ free_autopickup_exceptions()
struct autopickup_exception *ape;
while ((ape = g.apelist) != 0) {
regex_free(ape->regex);
free((genericptr_t) ape->pattern);
g.apelist = ape->next;
free((genericptr_t) ape);
free((genericptr_t) ape->pattern);
regex_free(ape->regex);
g.apelist = ape->next;
free((genericptr_t) ape);
}
}

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 save.c $NHDT-Date: 1581886866 2020/02/16 21:01:06 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.153 $ */
/* NetHack 3.6 save.c $NHDT-Date: 1590263454 2020/05/23 19:50:54 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.158 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Michael Allison, 2009. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1058,7 +1058,8 @@ NHFILE *nhfp;
if (nhfp->structlevel) {
bufoff(nhfp->fd);
/* bwrite() before bufon() uses plain write() */
bwrite(nhfp->fd, (genericptr_t) &sfsaveinfo, (unsigned) sizeof sfsaveinfo);
bwrite(nhfp->fd, (genericptr_t) &sfsaveinfo,
(unsigned) sizeof sfsaveinfo);
bufon(nhfp->fd);
}
return;
@@ -1149,7 +1150,11 @@ freedynamicdata()
/* miscellaneous */
/* free_pickinv_cache(); -- now done from really_done()... */
free_symsets();
#ifdef USER_SOUNDS
release_sound_mappings();
#endif
#endif /* FREE_ALL_MEMORY */
if (VIA_WINDOWPORT())
status_finish();
#ifdef DUMPLOG

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 sounds.c $NHDT-Date: 1582061574 2020/02/18 21:32:54 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.96 $ */
/* NetHack 3.6 sounds.c $NHDT-Date: 1590263455 2020/05/23 19:50:55 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.97 $ */
/* Copyright (c) 1989 Janet Walz, Mike Threepoint */
/* NetHack may be freely redistributed. See license for details. */
@@ -1269,7 +1269,7 @@ typedef struct audio_mapping_rec {
static audio_mapping *soundmap = 0;
char *sounddir = ".";
char *sounddir = 0; /* set in files.c */
/* adds a sound file mapping, returns 0 on failure, 1 on success */
int
@@ -1285,24 +1285,29 @@ const char *mapping;
filename, &volume) == 3) {
audio_mapping *new_map;
if (strlen(sounddir) + strlen(filename) > 254) {
if (!sounddir)
sounddir = dupstr(".");
if (strlen(sounddir) + 1 + strlen(filename) >= sizeof filespec) {
raw_print("sound file name too long");
return 0;
}
Sprintf(filespec, "%s/%s", sounddir, filename);
if (can_read_file(filespec)) {
new_map = (audio_mapping *) alloc(sizeof(audio_mapping));
new_map = (audio_mapping *) alloc(sizeof *new_map);
new_map->regex = regex_init();
new_map->filename = dupstr(filespec);
new_map->volume = volume;
new_map->next = soundmap;
if (!regex_compile(text, new_map->regex)) {
raw_print(regex_error_desc(new_map->regex));
const char *re_error_desc = regex_error_desc(new_map->regex);
regex_free(new_map->regex);
free(new_map->filename);
free(new_map);
free((genericptr_t) new_map->filename);
free((genericptr_t) new_map);
raw_print(re_error_desc);
return 0;
} else {
soundmap = new_map;
@@ -1334,6 +1339,23 @@ const char *msg;
}
}
void
release_sound_mappings()
{
audio_mapping *nextsound = 0;
while (soundmap) {
nextsound = soundmap->next;
regex_free(soundmap->regex);
free((genericptr_t) soundmap->filename);
free((genericptr_t) soundmap);
soundmap = nextsound;
}
if (sounddir)
free((genericptr_t) sounddir), sounddir = 0;
}
#endif /* USER_SOUNDS */
/*sounds.c*/