From 1c08982d56b1fbcc6394e2499b1c357a91365732 Mon Sep 17 00:00:00 2001 From: PatR Date: Thu, 25 Jan 2024 12:16:39 -0800 Subject: [PATCH] Strlen_() Restore its ability to reject a string longer than will fit within size_t that was lost by moving away from strnlen(). Determine the length inline rather than using strlen(). Move it from hacklib.c to alloc.c so that utility programs have easy access, and remove the copy of it from dlb_main.c. Fix a logic bug in str_start_is(). If a string was considered to be too long, it exited the loop when n was 0 but also performed post-decrement. So after the loop, n would be -1 and the 'if (n==0)' test would fail. panic() would occur if the initial string matched and happened to be LARGEST_INT-1 characters long. --- include/extern.h | 5 ++++- src/alloc.c | 35 +++++++++++++++++++++++++++++++---- src/hacklib.c | 21 +++------------------ util/dlb_main.c | 27 +++++---------------------- 4 files changed, 43 insertions(+), 45 deletions(-) diff --git a/include/extern.h b/include/extern.h index 247d21d3f..d0fb3b5de 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.7 extern.h $NHDT-Date: 1704225560 2024/01/02 19:59:20 $ $NHDT-Branch: keni-luabits2 $:$NHDT-Revision: 1.1358 $ */ +/* NetHack 3.7 extern.h $NHDT-Date: 1706213788 2024/01/25 20:16:28 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1373 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -78,6 +78,9 @@ extern char *fmt_ptr(const void *) NONNULL; extern int FITSint_(long long, const char *, int) NONNULLARG2; #define FITSuint(x) FITSuint_(x, __func__, __LINE__) extern unsigned FITSuint_(unsigned long long, const char *, int) NONNULLARG2; +/* for Strlen() which returns unsigned instead of size_t and panics for + strings of length INT_MAX (32K - 1) or longer */ +extern unsigned Strlen_(const char *, const char *, int) NONNULLPTRS; /* This next pre-processor directive covers almost the entire file, * interrupted only occasionally to pick up specific functions as needed. */ diff --git a/src/alloc.c b/src/alloc.c index 690ffd1f3..fcbfb3ffc 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -1,9 +1,8 @@ -/* NetHack 3.7 alloc.c $NHDT-Date: 1706082987 2024/01/24 07:56:27 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.33 $ */ +/* NetHack 3.7 alloc.c $NHDT-Date: 1706213795 2024/01/25 20:16:35 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.34 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ -/* to get the malloc() prototype from system.h */ #define ALLOC_C /* comment line for pre-compiled headers */ /* since this file is also used in auxiliary programs, don't include all the function declarations for all of nethack */ @@ -14,10 +13,17 @@ #include "nhlua.h" #endif -/*#define FITSint(x) FITSint_(x, __func__, (int) __LINE__)*/ +/* + * Some stuff that isn't allocation related but included is this file + * so that utility programs can access it more easily since they link + * with alloc.{o,obj}. + */ +/*#define FITSint(x) FITSint_(x, __func__, __LINE__)*/ extern int FITSint_(LUA_INTEGER, const char *, int) NONNULLARG2; -/*#define FITSuint(x) FITSuint_(x, __func__, (int) __LINE__)*/ +/*#define FITSuint(x) FITSuint_(x, __func__, __LINE__)*/ extern unsigned FITSuint_(unsigned long long, const char *, int) NONNULLARG2; +/*#define Strlen(s) Strlen_(s, __func__, __LINE__)*/ +extern unsigned Strlen_(const char *, const char *, int) NONNULLPTRS; char *fmt_ptr(const genericptr) NONNULL; @@ -271,4 +277,25 @@ FITSuint_(unsigned long long ull, const char *file, int line) return uret; } +/* strlen() but returns unsigned and panics if string is unreasonably long; + used by dlb as well as by nethack */ +unsigned +Strlen_( + const char *str, + const char *file, + int line) +{ + const char *p; + size_t len; + + /* strnlen(str, LARGEST_INT) w/o requiring posix.1 headers or libraries */ + for (p = str, len = 0; len < LARGEST_INT; ++len) + if (*p++ == '\0') + break; + + if (len == LARGEST_INT) + panic("%s:%d string too long", file, line); + return (unsigned) len; +} + /*alloc.c*/ diff --git a/src/hacklib.c b/src/hacklib.c index 6a642e13b..29e796927 100644 --- a/src/hacklib.c +++ b/src/hacklib.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 hacklib.c $NHDT-Date: 1705957184 2024/01/22 20:59:44 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.115 $ */ +/* NetHack 3.7 hacklib.c $NHDT-Date: 1706213796 2024/01/25 20:16:36 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.116 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2007. */ /* Copyright (c) Robert Patrick Rankin, 1991 */ @@ -24,7 +24,6 @@ char * strip_newline (char *) char * stripchars (char *, const char *, const char *) char * stripdigits (char *) - unsigned Strlen_ (const char *str, const char *, int) char * eos (char *) const char * c_eos (const char *) boolean str_start_is (const char *, const char *, boolean) @@ -233,20 +232,6 @@ c_eos(const char *s) return s; } -/* like strlen(3) but returns unsigned and panics if string is unreasonably long */ -unsigned -Strlen_( - const char *str, - const char *file, - int line) -{ - size_t len = strlen(str); - - if (len >= LARGEST_INT) - panic("%s:%d string too long", file, line); - return (unsigned) len; -} - /* determine whether 'str' starts with 'chkstr', possibly ignoring case; * panics on huge strings */ boolean @@ -255,10 +240,10 @@ str_start_is( const char *chkstr, boolean caseblind) { + char t1, t2; int n = LARGEST_INT; - while (n--) { - char t1, t2; + while (--n) { if (!*str) return (*chkstr == 0); /* chkstr >= str */ else if (!*chkstr) diff --git a/util/dlb_main.c b/util/dlb_main.c index bf9f493ac..e56485607 100644 --- a/util/dlb_main.c +++ b/util/dlb_main.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 dlb_main.c $NHDT-Date: 1705957188 2024/01/22 20:59:48 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.25 $ */ +/* NetHack 3.7 dlb_main.c $NHDT-Date: 1706213798 2024/01/25 20:16:38 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.27 $ */ /* Copyright (c) Kenneth Lorber, Bethesda, Maryland, 1993. */ /* NetHack may be freely redistributed. See license for details. */ @@ -18,8 +18,6 @@ ATTRNORETURN static void xexit(int) NORETURN; ATTRNORETURN extern void panic(const char *, ...) NORETURN; char *eos(char *); /* also used by dlb.c */ FILE *fopen_datafile(const char *, const char *); -unsigned FITSuint_(unsigned long long, const char *, int); -unsigned Strlen_(const char *, const char *, int); #ifdef DLB #ifdef DLBLIB @@ -367,8 +365,7 @@ main(int argc UNUSED_if_no_DLB, char **argv UNUSED_if_no_DLB) for (; ap < argc; ap++, nfiles++) { if (nfiles == ldlimit) grow_ld(&ld, &ldlimit, DLB_FILES_ALLOC / 5); - ld[nfiles].fname = (char *) alloc(Strlen(argv[ap]) + 1); - Strcpy(ld[nfiles].fname, argv[ap]); + ld[nfiles].fname = dupstr(argv[ap]); } } @@ -385,8 +382,7 @@ main(int argc UNUSED_if_no_DLB, char **argv UNUSED_if_no_DLB) if (nfiles == ldlimit) grow_ld(&ld, &ldlimit, DLB_FILES_ALLOC / 5); *(eos(buf) - 1) = '\0'; /* strip newline */ - ld[nfiles].fname = (char *) alloc((int)strlen(buf) + 1); - Strcpy(ld[nfiles].fname, buf); + ld[nfiles].fname = dupstr(buf); } fclose(list); } @@ -409,7 +405,7 @@ main(int argc UNUSED_if_no_DLB, char **argv UNUSED_if_no_DLB) ld[i].fsize = lseek(fd, 0, SEEK_END); ld[i].foffset = flen; - slen += strlen(ld[i].fname); /* don't add null (yet) */ + slen += (long) strlen(ld[i].fname); /* don't add null (yet) */ flen += ld[i].fsize; close(fd); } @@ -425,7 +421,7 @@ main(int argc UNUSED_if_no_DLB, char **argv UNUSED_if_no_DLB) /* caculate directory size */ dir_size = 40 /* header line (see below) */ + ((nfiles + 1) * 11) /* handling+file offset+SP+newline */ - + slen + strlen(DLB_DIRECTORY); /* file names */ + + slen + (long) strlen(DLB_DIRECTORY); /* file names */ /* write directory */ write_dlb_directory(out, nfiles, ld, slen, dir_size, flen); @@ -552,17 +548,4 @@ xexit(int retcd) /*NOTREACHED*/ } -/* from hacklib.c */ -unsigned -Strlen_(const char *str, const char *file, int line) -{ - size_t len = strlen(str); - - if (len >= LARGEST_INT) { - panic("%s:%d string too long", file, line); - /*NOTREACHED*/ - } - return (unsigned) len; -} - /*dlb_main.c*/