Module Name:    src
Committed By:   rillig
Date:           Fri Feb 16 19:53:40 UTC 2024

Modified Files:
        src/common/lib/libutil: snprintb.c
        src/tests/lib/libutil: t_snprintb.c

Log Message:
snprintb: eliminate two local variables, allow zero-size buffer

Like snprintf, the buffer size may be zero. Unlike snprintf, the buffer
must not be NULL.


To generate a diff of this commit:
cvs rdiff -u -r1.32 -r1.33 src/common/lib/libutil/snprintb.c
cvs rdiff -u -r1.19 -r1.20 src/tests/lib/libutil/t_snprintb.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/common/lib/libutil/snprintb.c
diff -u src/common/lib/libutil/snprintb.c:1.32 src/common/lib/libutil/snprintb.c:1.33
--- src/common/lib/libutil/snprintb.c:1.32	Fri Feb 16 19:31:25 2024
+++ src/common/lib/libutil/snprintb.c	Fri Feb 16 19:53:40 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: snprintb.c,v 1.32 2024/02/16 19:31:25 rillig Exp $	*/
+/*	$NetBSD: snprintb.c,v 1.33 2024/02/16 19:53:40 rillig Exp $	*/
 
 /*-
  * Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -41,7 +41,7 @@
 
 #  include <sys/cdefs.h>
 #  if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: snprintb.c,v 1.32 2024/02/16 19:31:25 rillig Exp $");
+__RCSID("$NetBSD: snprintb.c,v 1.33 2024/02/16 19:53:40 rillig Exp $");
 #  endif
 
 #  include <sys/types.h>
@@ -51,7 +51,7 @@ __RCSID("$NetBSD: snprintb.c,v 1.32 2024
 #  include <errno.h>
 # else /* ! _KERNEL */
 #  include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: snprintb.c,v 1.32 2024/02/16 19:31:25 rillig Exp $");
+__KERNEL_RCSID(0, "$NetBSD: snprintb.c,v 1.33 2024/02/16 19:53:40 rillig Exp $");
 #  include <sys/param.h>
 #  include <sys/inttypes.h>
 #  include <sys/systm.h>
@@ -63,7 +63,6 @@ int
 snprintb_m(char *buf, size_t bufsize, const char *bitfmt, uint64_t val,
 	   size_t line_max)
 {
-	char *bp = buf, *sep_bp = NULL;
 	const char *num_fmt, *cur_bitfmt, *sep_bitfmt = NULL;
 	char sep;
 	int restart = 0;
@@ -97,39 +96,33 @@ snprintb_m(char *buf, size_t bufsize, co
 	if (line_max > 0)
 		bufsize--;
 
-	int val_len = snprintf(bp, bufsize, num_fmt, (uintmax_t)val);
+	int val_len = snprintf(buf, bufsize, num_fmt, (uintmax_t)val);
 	if (val_len < 0)
 		goto internal;
 
 	size_t total_len = val_len, line_len = val_len, sep_line_len = 0;
 
-	if (total_len < bufsize)
-		bp += total_len;
-	else
-		bp += bufsize - 1;
-
 #define	STORE(c) do {							\
+		if (total_len < bufsize)				\
+			buf[total_len] = (c);				\
+		total_len++;						\
 		line_len++;						\
-		if (++total_len < bufsize)				\
-			*bp++ = (c);					\
 	} while (0)
 
 #define	BACKUP() do {							\
-		if (sep_bp != NULL) {					\
-			bp = sep_bp;					\
-			sep_bp = NULL;					\
+		if (sep_line_len > 0) {					\
 			total_len -= line_len - sep_line_len;		\
+			sep_line_len = 0;				\
 			restart = 1;					\
 			bitfmt = sep_bitfmt;				\
 		}							\
 		STORE('>');						\
 		STORE('\0');						\
 		if (total_len < bufsize)				\
-			snprintf(bp, bufsize - total_len, num_fmt,	\
-			    (uintmax_t)val);				\
+			snprintf(buf + total_len, bufsize - total_len,	\
+			    num_fmt, (uintmax_t)val);			\
 		total_len += val_len;					\
 		line_len = val_len;					\
-		bp += val_len;						\
 	} while (0)
 
 #define	PUTSEP() do {							\
@@ -137,10 +130,8 @@ snprintb_m(char *buf, size_t bufsize, co
 			BACKUP();					\
 			STORE('<');					\
 		} else {						\
-			/* Remember separator location */		\
 			if (line_max > 0 && sep != '<') {		\
 				sep_line_len = line_len;		\
-				sep_bp = bp;				\
 				sep_bitfmt = cur_bitfmt;		\
 			}						\
 			STORE(sep);					\
@@ -170,15 +161,13 @@ snprintb_m(char *buf, size_t bufsize, co
 	} while (0)
 
 #define	FMTSTR(sb, f) do {						\
-		size_t n = total_len < bufsize				\
-		    ? bufsize - total_len : 0;				\
+		char *bp = total_len < bufsize ? buf + total_len : NULL; \
+		size_t n = total_len < bufsize ? bufsize - total_len : 0; \
 		int fmt_len = snprintf(bp, n, sb, (uintmax_t)f);	\
 		if (fmt_len < 0)					\
 			goto internal;					\
 		total_len += fmt_len;					\
 		line_len += fmt_len;					\
-		if (total_len < bufsize)				\
-			bp += fmt_len;					\
 	} while (0)
 
 	sep = '<';

Index: src/tests/lib/libutil/t_snprintb.c
diff -u src/tests/lib/libutil/t_snprintb.c:1.19 src/tests/lib/libutil/t_snprintb.c:1.20
--- src/tests/lib/libutil/t_snprintb.c:1.19	Fri Feb 16 19:20:38 2024
+++ src/tests/lib/libutil/t_snprintb.c	Fri Feb 16 19:53:40 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: t_snprintb.c,v 1.19 2024/02/16 19:20:38 rillig Exp $ */
+/* $NetBSD: t_snprintb.c,v 1.20 2024/02/16 19:53:40 rillig Exp $ */
 
 /*
  * Copyright (c) 2002, 2004, 2008, 2010, 2024 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
 #include <sys/cdefs.h>
 __COPYRIGHT("@(#) Copyright (c) 2008, 2010\
  The NetBSD Foundation, inc. All rights reserved.");
-__RCSID("$NetBSD: t_snprintb.c,v 1.19 2024/02/16 19:20:38 rillig Exp $");
+__RCSID("$NetBSD: t_snprintb.c,v 1.20 2024/02/16 19:53:40 rillig Exp $");
 
 #include <stdio.h>
 #include <string.h>
@@ -79,9 +79,6 @@ h_snprintb_loc(const char *file, size_t 
 {
 	char buf[1024];
 
-	// Calling snprintb with bufsize == 0 invokes undefined
-	// behavior due to out-of-range 'bp'.
-	ATF_REQUIRE(bufsize > 0);
 	ATF_REQUIRE(bufsize <= sizeof(buf));
 	ATF_REQUIRE(reslen <= sizeof(buf));
 
@@ -90,8 +87,11 @@ h_snprintb_loc(const char *file, size_t 
 	ATF_REQUIRE(rv >= 0);
 	size_t rlen = rv;
 
+	if (bufsize == 0 && reslen == 1)
+		reslen = 0;
 	ATF_CHECK_MSG(
-	    rv == exp_rv && memcmp(buf, res, reslen) == 0
+	    rv == exp_rv
+	    && memcmp(buf, res, reslen) == 0
 	    && buf[rlen < bufsize ? rlen : bufsize - 1] == '\0',
 	    "failed:\n"
 	    "\ttest case: %s:%zu\n"
@@ -244,14 +244,10 @@ ATF_TC_BODY(snprintb, tc)
 	h_snprintb_error(
 	    "\377");
 
-	// old-style format, small buffer
-#if 0
-	// FIXME: Calling snprintb with buffer size 0 invokes undefined
-	// behavior due to out-of-bounds 'bp' pointer.
+	// old-style format, small buffers
 	h_snprintb_len(
 	    0, "\020", 0,
 	    1, "");
-#endif
 	h_snprintb_len(
 	    1, "\020", 0,
 	    1, "");
@@ -599,14 +595,10 @@ ATF_TC_BODY(snprintb, tc)
 		    expected);
 	}
 
-	// new-style format, small buffer
-#if 0
-	// FIXME: Calling snprintb with buffer size 0 invokes undefined
-	// behavior due to out-of-bounds 'bp' pointer.
+	// new-style format, small buffers
 	h_snprintb_len(
 	    0, "\177\020", 0,
 	    1, "");
-#endif
 	h_snprintb_len(
 	    1, "\177\020", 0,
 	    1, "");
@@ -653,7 +645,7 @@ h_snprintb_m_loc(const char *file, size_
 {
 	char buf[1024];
 
-	ATF_REQUIRE(bufsize > 1);
+	ATF_REQUIRE(bufsize > 0);
 	ATF_REQUIRE(bufsize <= sizeof(buf));
 	ATF_REQUIRE(reslen <= sizeof(buf));
 

Reply via email to