From: PatR Date: Sun, 9 May 2021 01:02:00 +0000 (-0700) Subject: fix github issue #507 - filename buffer overflow X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c866c9022b949f0c0969c9b13c12adb31b7629c5;p=nethack fix github issue #507 - filename buffer overflow when compressing or uncompressing a save file. Defining VAR_PLAYGROUND forces PREFIXES_IN_USE to be defined, and the latter causes docompress_file() to be called with save file name containing a full path instead of just save/xyzzy.Z relative to the playground. Depending on the value of VAR_PLAYGROUND, that could be too long for the buffer used to make a copy of the name with ".Z"/".gz"/".bz2" appended. Probably only applies to Unix/linux/OSX configurations. Fixes #507 --- diff --git a/doc/fixes37.0 b/doc/fixes37.0 index e0c478227..6ccdc2571 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -1,4 +1,4 @@ -NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.527 $ $NHDT-Date: 1620413928 2021/05/07 18:58:48 $ +NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.528 $ $NHDT-Date: 1620522110 2021/05/09 01:01:50 $ General Fixes and Modified Features ----------------------------------- @@ -504,6 +504,10 @@ when an unseen non-pet picks up or uses an item, hero loses known/dknown/ particular, player won't be asked what to call unseen thrown potion) wishing for a partly eaten wraith corpse yielded "partly eaten food (1) more nutritious than untouched food (0)" +if PREFIXES_IN_USE was defined (and VAR_PLAYGROUND forces it to be) when + COMPRESS was also defined (external save and bones file compression + via fork()+exec()), the file name buffer in docompress_file() wasn't + big enough so could overflow and trigger a crash Fixes to 3.7.0-x Problems that Were Exposed Via git Repository diff --git a/src/files.c b/src/files.c index 58ede76f8..66f509633 100644 --- a/src/files.c +++ b/src/files.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 files.c $NHDT-Date: 1612819003 2021/02/08 21:16:43 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.331 $ */ +/* NetHack 3.7 files.c $NHDT-Date: 1620522110 2021/05/09 01:01:50 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.334 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1312,7 +1312,7 @@ free_saved_games(char **saved) /* ---------- BEGIN FILE COMPRESSION HANDLING ----------- */ -#ifdef COMPRESS +#ifdef COMPRESS /* external compression */ static void redirect(const char *filename, const char *mode, FILE *stream, boolean uncomp) @@ -1341,7 +1341,8 @@ redirect(const char *filename, const char *mode, FILE *stream, boolean uncomp) static void docompress_file(const char *filename, boolean uncomp) { - char cfn[SAVESIZE]; + char *cfn = 0; + const char *xtra; FILE *cf; const char *args[10]; #ifdef COMPRESS_OPTIONS @@ -1349,18 +1350,27 @@ docompress_file(const char *filename, boolean uncomp) #endif int i = 0; int f; + unsigned ln; #ifdef TTY_GRAPHICS boolean istty = WINDOWPORT("tty"); #endif - Strcpy(cfn, filename); #ifdef COMPRESS_EXTENSION - Strcat(cfn, COMPRESS_EXTENSION); + xtra = COMPRESS_EXTENSION; +#else + xtra = ""; #endif + ln = (unsigned) (strlen(filename) + strlen(xtra)); + cfn = (char *) alloc(ln + 1); + Strcpy(cfn, filename); + Strcat(cfn, xtra); + /* when compressing, we know the file exists */ if (uncomp) { - if ((cf = fopen(cfn, RDBMODE)) == (FILE *) 0) + if ((cf = fopen(cfn, RDBMODE)) == (FILE *) 0) { + free((genericptr_t) cfn); return; + } (void) fclose(cf); } @@ -1431,10 +1441,12 @@ docompress_file(const char *filename, boolean uncomp) perror((char *) 0); (void) fprintf(stderr, "Exec to %scompress %s failed.\n", uncomp ? "un" : "", filename); + free((genericptr_t) cfn); nh_terminate(EXIT_FAILURE); } else if (f == -1) { perror((char *) 0); pline("Fork to %scompress %s failed.", uncomp ? "un" : "", filename); + free((genericptr_t) cfn); return; } #ifndef NO_SIGNAL @@ -1483,8 +1495,11 @@ docompress_file(const char *filename, boolean uncomp) } #endif } + + free((genericptr_t) cfn); } -#endif /* COMPRESS */ + +#endif /* COMPRESS : external compression */ #if defined(COMPRESS) || defined(ZLIB_COMP) #define UNUSED_if_not_COMPRESS /*empty*/ @@ -3840,7 +3855,7 @@ recover_savefile(void) struct savefile_info sfi; char tmpplbuf[PL_NSIZ]; const char *savewrite_failure = (const char *) 0; - + for (lev = 0; lev < 256; lev++) processed[lev] = 0; @@ -3937,7 +3952,7 @@ recover_savefile(void) if (savewrite_failure) goto cleanup; - if (snhfp->structlevel) { + if (snhfp->structlevel) { if (write(snhfp->fd, (genericptr_t) &pltmpsiz, sizeof pltmpsiz) != sizeof pltmpsiz) savewrite_failure = "player name size";