Module Name:    src
Committed By:   christos
Date:           Sat Apr 27 17:45:28 UTC 2019

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

Log Message:
Fix an off-by-one in the F modifier that ended up skipping the first : or =
entry, and add a * specifier for a "default case".


To generate a diff of this commit:
cvs rdiff -u -r1.18 -r1.19 src/common/lib/libutil/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.18 src/common/lib/libutil/snprintb.c:1.19
--- src/common/lib/libutil/snprintb.c:1.18	Wed Jul 25 20:33:26 2018
+++ src/common/lib/libutil/snprintb.c	Sat Apr 27 13:45:28 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: snprintb.c,v 1.18 2018/07/26 00:33:26 kamil Exp $	*/
+/*	$NetBSD: snprintb.c,v 1.19 2019/04/27 17:45:28 christos 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.18 2018/07/26 00:33:26 kamil Exp $");
+__RCSID("$NetBSD: snprintb.c,v 1.19 2019/04/27 17:45:28 christos Exp $");
 #  endif
 
 #  include <sys/types.h>
@@ -51,7 +51,7 @@ __RCSID("$NetBSD: snprintb.c,v 1.18 2018
 #  include <errno.h>
 # else /* ! _KERNEL */
 #  include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: snprintb.c,v 1.18 2018/07/26 00:33:26 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: snprintb.c,v 1.19 2019/04/27 17:45:28 christos Exp $");
 #  include <sys/param.h>
 #  include <sys/inttypes.h>
 #  include <sys/systm.h>
@@ -67,7 +67,7 @@ snprintb_m(char *buf, size_t buflen, con
 	const char *c_fmt, *s_fmt = NULL, *cur_fmt;
 	const char *sbase;
 	int bit, ch, t_len, s_len = 0, l_len, f_len, v_len, sep;
-	int restart = 0;
+	int restart = 0, matched = 1;
 	uint64_t field;
 
 #ifdef _KERNEL
@@ -166,6 +166,16 @@ snprintb_m(char *buf, size_t buflen, con
 			if (restart)					\
 				break;					\
 		}
+#define FMTSTR(sb, f) 							\
+	do { 								\
+		f_len = snprintf(bp, buflen - t_len, sb, (int)f);	\
+		if (f_len < 0) 						\
+			goto internal; 					\
+		t_len += f_len; 					\
+		l_len += f_len; 					\
+		if ((size_t)t_len < buflen) 				\
+			bp += f_len; 					\
+	} while (/*CONSTCOND*/0)
 
 	/*
 	 * Chris Torek's new bitmask format is identified by a leading \177
@@ -208,6 +218,7 @@ snprintb_m(char *buf, size_t buflen, con
 				break;
 			case 'f':
 			case 'F':
+				matched = 0;
 				cur_fmt = c_fmt;
 				f_len = *bitfmt++;	/* field length */
 				field = (val >> bit) &
@@ -215,23 +226,14 @@ snprintb_m(char *buf, size_t buflen, con
 				PUTSEP;
 				if (restart == 0)
 					sep = ',';
-				if (ch == 'F') {	/* just extract */
-					bitfmt--;
+				if (ch == 'F') 		/* just extract */
 					break;
-				}
 				if (restart == 0)
 					PUTS(bitfmt);
 				if (restart == 0)
 					PUTCHR('=');
 				if (restart == 0) {
-					f_len = snprintf(bp, buflen - t_len,
-							 sbase, field);
-					if (f_len < 0)
-						goto internal;
-					t_len += f_len;
-					l_len += f_len;
-					if ((size_t)t_len < buflen)
-						bp += f_len;
+					FMTSTR(sbase, field);
 					if (l_max > 0 && (size_t)l_len > l_max)
 						PUTCHR('#');
 				}
@@ -246,10 +248,19 @@ snprintb_m(char *buf, size_t buflen, con
 				 */
 				if ((int)field != bit)
 					goto skip;
+				matched = 1;
 				if (ch == '=')
 					PUTCHR('=');
 				PUTS(bitfmt);
 				break;
+			case '*':
+				bitfmt--;
+				if (!matched) {
+					matched = 1;
+					FMTSTR(bitfmt, field);
+					break;
+				}
+				/*FALLTHROUGH*/
 			default:
 			skip:
 				while (*bitfmt++ != '\0')

Reply via email to