From 915a3d5b7be87a66bc3c3e1652c596658962e6a1 Mon Sep 17 00:00:00 2001
From: Mark Adler <madler@alumni.caltech.edu>
Date: Tue, 6 Feb 2024 14:27:50 -0800
Subject: Avoid use of snprintf() in test/minigzip.c.

It was being used only as a safe version of strcpy(). Instead, use
a safe alternative to strcpy().
---
 test/minigzip.c | 56 +++++++++++++++++++++++++++-----------------------------
 1 file changed, 27 insertions(+), 29 deletions(-)

diff --git a/test/minigzip.c b/test/minigzip.c
index 974a98d..aa787fc 100644
--- a/test/minigzip.c
+++ b/test/minigzip.c
@@ -44,10 +44,6 @@
 #  define SET_BINARY_MODE(file)
 #endif
 
-#if defined(_MSC_VER) && _MSC_VER < 1900
-#  define snprintf _snprintf
-#endif
-
 #ifdef VMS
 #  define unlink delete
 #  define GZ_SUFFIX "-gz"
@@ -148,6 +144,25 @@ static void pwinerror (s)
 #  define local
 #endif
 
+/* ===========================================================================
+ * Safe string copy. Copy up to len bytes from src to dst, if src terminates
+ * with a null by then. If not, copy len-1 bytes from src, terminating it with
+ * a null in dst[len-1], cutting src short. Return a pointer to the terminating
+ * null. If len is zero, nothing is written to *dst and NULL is returned.
+ */
+static char *string_copy(char *dst, char const *src, z_size_t len) {
+    if (len == 0)
+        return NULL;
+    while (--len) {
+        *dst = *src++;
+        if (*dst == 0)
+            return dst;
+        dst++;
+    }
+    *dst = 0;
+    return dst;
+}
+
 #ifdef Z_SOLO
 /* for Z_SOLO, create simplified gz* functions using deflate and inflate */
 
@@ -397,7 +412,7 @@ static void gz_uncompress(gzFile in, FILE *out) {
  * original.
  */
 static void file_compress(char *file, char *mode) {
-    local char outfile[MAX_NAME_LEN];
+    local char outfile[MAX_NAME_LEN+1], *end;
     FILE  *in;
     gzFile out;
 
@@ -406,12 +421,8 @@ static void file_compress(char *file, char *mode) {
         exit(1);
     }
 
-#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
-    snprintf(outfile, sizeof(outfile), "%s%s", file, GZ_SUFFIX);
-#else
-    strcpy(outfile, file);
-    strcat(outfile, GZ_SUFFIX);
-#endif
+    end = string_copy(outfile, file, sizeof(outfile));
+    string_copy(end, GZ_SUFFIX, (outfile + sizeof(outfile)) - end);
 
     in = fopen(file, "rb");
     if (in == NULL) {
@@ -433,7 +444,7 @@ static void file_compress(char *file, char *mode) {
  * Uncompress the given file and remove the original.
  */
 static void file_uncompress(char *file) {
-    local char buf[MAX_NAME_LEN];
+    local char buf[MAX_NAME_LEN+1];
     char *infile, *outfile;
     FILE  *out;
     gzFile in;
@@ -444,11 +455,7 @@ static void file_uncompress(char *file) {
         exit(1);
     }
 
-#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
-    snprintf(buf, sizeof(buf), "%s", file);
-#else
-    strcpy(buf, file);
-#endif
+    string_copy(buf, file, sizeof(buf));
 
     if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {
         infile = file;
@@ -457,11 +464,7 @@ static void file_uncompress(char *file) {
     } else {
         outfile = file;
         infile = buf;
-#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
-        snprintf(buf + len, sizeof(buf) - len, "%s", GZ_SUFFIX);
-#else
-        strcat(infile, GZ_SUFFIX);
-#endif
+        string_copy(buf + len, GZ_SUFFIX, sizeof(buf) - len);
     }
     in = gzopen(infile, "rb");
     if (in == NULL) {
@@ -494,14 +497,9 @@ int main(int argc, char *argv[]) {
     int copyout = 0;
     int uncompr = 0;
     gzFile file;
-    char *bname, outmode[20];
-
-#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
-    snprintf(outmode, sizeof(outmode), "%s", "wb6 ");
-#else
-    strcpy(outmode, "wb6 ");
-#endif
+    char *bname, outmode[5];
 
+    string_copy(outmode, "wb6 ", sizeof(outmode));
     prog = argv[0];
     bname = strrchr(argv[0], '/');
     if (bname)
-- 
cgit v1.2.3-55-g6feb