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
+2 -1
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. */ /* Copyright (c) Steve Creps, 1988. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -2459,6 +2459,7 @@ E int NDECL(tiphat);
#ifdef USER_SOUNDS #ifdef USER_SOUNDS
E int FDECL(add_sound_mapping, (const char *)); E int FDECL(add_sound_mapping, (const char *));
E void FDECL(play_sound_for_message, (const char *)); E void FDECL(play_sound_for_message, (const char *));
E void NDECL(release_sound_mappings);
#endif #endif
/* ### sp_lev.c ### */ /* ### sp_lev.c ### */
+4 -2
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) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Derek S. Ray, 2015. */ /*-Copyright (c) Derek S. Ray, 2015. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -120,7 +120,7 @@ extern char *FDECL(translate_path_variables, (const char *, char *));
#endif #endif
#ifdef USER_SOUNDS #ifdef USER_SOUNDS
extern char *sounddir; extern char *sounddir; /* defined in sounds.c */
#endif #endif
#if defined(UNIX) && defined(QT_GRAPHICS) #if defined(UNIX) && defined(QT_GRAPHICS)
@@ -2885,6 +2885,8 @@ char *origbuf;
#endif /*AMIGA*/ #endif /*AMIGA*/
#ifdef USER_SOUNDS #ifdef USER_SOUNDS
} else if (match_varname(buf, "SOUNDDIR", 8)) { } else if (match_varname(buf, "SOUNDDIR", 8)) {
if (sounddir)
free((genericptr_t) sounddir);
sounddir = dupstr(bufp); sounddir = dupstr(bufp);
} else if (match_varname(buf, "SOUND", 5)) { } else if (match_varname(buf, "SOUND", 5)) {
add_sound_mapping(bufp); add_sound_mapping(bufp);
+49 -29
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) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Michael Allison, 2008. */ /*-Copyright (c) Michael Allison, 2008. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -5447,7 +5447,7 @@ handler_menu_colors(VOID_ARGS)
if (*mcbuf == '\033') if (*mcbuf == '\033')
goto menucolors_done; goto menucolors_done;
if (*mcbuf if (*mcbuf
&& test_regex_pattern(mcbuf, (const char *)0) && test_regex_pattern(mcbuf, "MENUCOLORS regex")
&& (mcclr = query_color((char *) 0)) != -1 && (mcclr = query_color((char *) 0)) != -1
&& (mcattr = query_attr((char *) 0)) != -1 && (mcattr = query_attr((char *) 0)) != -1
&& !add_menu_coloring_parsed(mcbuf, mcclr, mcattr)) { && !add_menu_coloring_parsed(mcbuf, mcclr, mcattr)) {
@@ -5529,7 +5529,7 @@ handler_msgtype(VOID_ARGS)
if (*mtbuf == '\033') if (*mtbuf == '\033')
return TRUE; return TRUE;
if (*mtbuf if (*mtbuf
&& test_regex_pattern(mtbuf, (const char *)0) && test_regex_pattern(mtbuf, "MSGTYPE regex")
&& (mttyp = query_msgtype()) != -1 && (mttyp = query_msgtype()) != -1
&& !msgtype_add(mttyp, mtbuf)) { && !msgtype_add(mttyp, mtbuf)) {
pline("Error adding the message type."); pline("Error adding the message type.");
@@ -6671,16 +6671,20 @@ msgtype_add(typ, pattern)
int typ; int typ;
char *pattern; char *pattern;
{ {
static const char *re_error = "MSGTYPE regex error";
struct plinemsg_type *tmp = (struct plinemsg_type *) alloc(sizeof *tmp); struct plinemsg_type *tmp = (struct plinemsg_type *) alloc(sizeof *tmp);
tmp->msgtype = typ; tmp->msgtype = typ;
tmp->regex = regex_init(); 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)) { 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); regex_free(tmp->regex);
free((genericptr_t) tmp); free((genericptr_t) tmp);
config_error_add("%s: %s", re_error, re_error_desc);
return FALSE; return FALSE;
} }
tmp->pattern = dupstr(pattern); tmp->pattern = dupstr(pattern);
@@ -6805,30 +6809,40 @@ char *str;
return FALSE; 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 static boolean
test_regex_pattern(str, errmsg) test_regex_pattern(str, errmsg)
const char *str; const char *str;
const char *errmsg; const char *errmsg;
{ {
static const char re_error[] = "Regex error"; static const char def_errmsg[] = "NHregex error";
struct nhregex *match; struct nhregex *match;
boolean retval = TRUE; const char *re_error_desc;
boolean retval;
if (!str) if (!str)
return FALSE; return FALSE;
if (!errmsg)
errmsg = def_errmsg;
match = regex_init(); match = regex_init();
if (!match) { if (!match) {
config_error_add("NHregex error"); config_error_add("%s", errmsg);
return FALSE; return FALSE;
} }
if (!regex_compile(str, match)) { retval = regex_compile(str, match);
config_error_add("%s: %s", errmsg ? errmsg : re_error, /* get potential error message before freeing regexp and free regexp
regex_error_desc(match)); before issuing message in case the error is "ran out of memory"
retval = FALSE; 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); regex_free(match);
/* if returning failure, tell player */
if (!retval)
config_error_add("%s: %s", errmsg, re_error_desc);
return retval; return retval;
} }
@@ -6844,19 +6858,23 @@ int c, a;
return FALSE; return FALSE;
tmp = (struct menucoloring *) alloc(sizeof *tmp); tmp = (struct menucoloring *) alloc(sizeof *tmp);
tmp->match = regex_init(); 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)) { 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); regex_free(tmp->match);
free(tmp); free((genericptr_t) tmp);
config_error_add("%s: %s", re_error, re_error_desc);
return FALSE; 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 */ /* 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->origstr);
free((genericptr_t) tmp); free((genericptr_t) tmp);
} }
g.menu_colorings = (struct menucoloring *) 0;
} }
static void static void
@@ -7752,13 +7771,14 @@ const char *mapping;
ape = (struct autopickup_exception *) alloc(sizeof *ape); ape = (struct autopickup_exception *) alloc(sizeof *ape);
ape->regex = regex_init(); ape->regex = regex_init();
if (!regex_compile(text, ape->regex)) { if (!regex_compile(text, ape->regex)) {
config_error_add("%s: %s", APE_regex_error, const char *re_error_desc = regex_error_desc(ape->regex);
regex_error_desc(ape->regex));
/* free first in case reason for failure was insufficient memory */
regex_free(ape->regex); regex_free(ape->regex);
free((genericptr_t) ape); free((genericptr_t) ape);
config_error_add("%s: %s", APE_regex_error, re_error_desc);
return 0; return 0;
} }
ape->pattern = dupstr(text); ape->pattern = dupstr(text);
ape->grab = grab; ape->grab = grab;
ape->next = g.apelist; ape->next = g.apelist;
@@ -7796,10 +7816,10 @@ free_autopickup_exceptions()
struct autopickup_exception *ape; struct autopickup_exception *ape;
while ((ape = g.apelist) != 0) { while ((ape = g.apelist) != 0) {
regex_free(ape->regex); free((genericptr_t) ape->pattern);
free((genericptr_t) ape->pattern); regex_free(ape->regex);
g.apelist = ape->next; g.apelist = ape->next;
free((genericptr_t) ape); free((genericptr_t) ape);
} }
} }
+7 -2
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) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Michael Allison, 2009. */ /*-Copyright (c) Michael Allison, 2009. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -1058,7 +1058,8 @@ NHFILE *nhfp;
if (nhfp->structlevel) { if (nhfp->structlevel) {
bufoff(nhfp->fd); bufoff(nhfp->fd);
/* bwrite() before bufon() uses plain write() */ /* 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); bufon(nhfp->fd);
} }
return; return;
@@ -1149,7 +1150,11 @@ freedynamicdata()
/* miscellaneous */ /* miscellaneous */
/* free_pickinv_cache(); -- now done from really_done()... */ /* free_pickinv_cache(); -- now done from really_done()... */
free_symsets(); free_symsets();
#ifdef USER_SOUNDS
release_sound_mappings();
#endif
#endif /* FREE_ALL_MEMORY */ #endif /* FREE_ALL_MEMORY */
if (VIA_WINDOWPORT()) if (VIA_WINDOWPORT())
status_finish(); status_finish();
#ifdef DUMPLOG #ifdef DUMPLOG
+29 -7
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 */ /* Copyright (c) 1989 Janet Walz, Mike Threepoint */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -1269,7 +1269,7 @@ typedef struct audio_mapping_rec {
static audio_mapping *soundmap = 0; 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 */ /* adds a sound file mapping, returns 0 on failure, 1 on success */
int int
@@ -1285,24 +1285,29 @@ const char *mapping;
filename, &volume) == 3) { filename, &volume) == 3) {
audio_mapping *new_map; 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"); raw_print("sound file name too long");
return 0; return 0;
} }
Sprintf(filespec, "%s/%s", sounddir, filename); Sprintf(filespec, "%s/%s", sounddir, filename);
if (can_read_file(filespec)) { 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->regex = regex_init();
new_map->filename = dupstr(filespec); new_map->filename = dupstr(filespec);
new_map->volume = volume; new_map->volume = volume;
new_map->next = soundmap; new_map->next = soundmap;
if (!regex_compile(text, new_map->regex)) { 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); regex_free(new_map->regex);
free(new_map->filename); free((genericptr_t) new_map->filename);
free(new_map); free((genericptr_t) new_map);
raw_print(re_error_desc);
return 0; return 0;
} else { } else {
soundmap = new_map; 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 */ #endif /* USER_SOUNDS */
/*sounds.c*/ /*sounds.c*/