Module Name:    src
Committed By:   rillig
Date:           Sun Apr  7 15:20:17 UTC 2024

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

Log Message:
snprintb: reject empty bit descriptions and wrongly placed defaults


To generate a diff of this commit:
cvs rdiff -u -r1.47 -r1.48 src/common/lib/libutil/snprintb.c
cvs rdiff -u -r1.34 -r1.35 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.47 src/common/lib/libutil/snprintb.c:1.48
--- src/common/lib/libutil/snprintb.c:1.47	Sun Apr  7 12:05:23 2024
+++ src/common/lib/libutil/snprintb.c	Sun Apr  7 15:20:16 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: snprintb.c,v 1.47 2024/04/07 12:05:23 rillig Exp $	*/
+/*	$NetBSD: snprintb.c,v 1.48 2024/04/07 15:20:16 rillig Exp $	*/
 
 /*-
  * Copyright (c) 2002, 2024 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
 
 #  include <sys/cdefs.h>
 #  if defined(LIBC_SCCS)
-__RCSID("$NetBSD: snprintb.c,v 1.47 2024/04/07 12:05:23 rillig Exp $");
+__RCSID("$NetBSD: snprintb.c,v 1.48 2024/04/07 15:20:16 rillig Exp $");
 #  endif
 
 #  include <sys/types.h>
@@ -46,7 +46,7 @@ __RCSID("$NetBSD: snprintb.c,v 1.47 2024
 #  include <errno.h>
 # else /* ! _KERNEL */
 #  include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: snprintb.c,v 1.47 2024/04/07 12:05:23 rillig Exp $");
+__KERNEL_RCSID(0, "$NetBSD: snprintb.c,v 1.48 2024/04/07 15:20:16 rillig Exp $");
 #  include <sys/param.h>
 #  include <sys/inttypes.h>
 #  include <sys/systm.h>
@@ -133,15 +133,17 @@ old_style(state *s)
 	while (*s->bitfmt != '\0') {
 		const char *cur_bitfmt = s->bitfmt;
 		uint8_t bit = *s->bitfmt;
-		if (bit > ' ')
+		if (bit > 32)
+			return -1;
+		if ((uint8_t)cur_bitfmt[1] <= 32)
 			return -1;
 		if (s->val & (1U << (bit - 1))) {
 			store_delimiter(s);
-			while ((uint8_t)*++s->bitfmt > ' ')
+			while ((uint8_t)*++s->bitfmt > 32)
 				store(s, *s->bitfmt);
 			maybe_wrap_line(s, cur_bitfmt);
 		} else
-			while ((uint8_t)*++s->bitfmt > ' ')
+			while ((uint8_t)*++s->bitfmt > 32)
 				continue;
 	}
 	return 0;
@@ -222,6 +224,7 @@ new_style(state *s)
 		case '*':
 			if (field_kind == 0)
 				return -1;
+			field_kind = 0;
 			if (cur_bitfmt[1] == '\0')
 				return -1;
 			s->bitfmt++;

Index: src/tests/lib/libutil/t_snprintb.c
diff -u src/tests/lib/libutil/t_snprintb.c:1.34 src/tests/lib/libutil/t_snprintb.c:1.35
--- src/tests/lib/libutil/t_snprintb.c:1.34	Sun Apr  7 12:05:23 2024
+++ src/tests/lib/libutil/t_snprintb.c	Sun Apr  7 15:20:17 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: t_snprintb.c,v 1.34 2024/04/07 12:05:23 rillig Exp $ */
+/* $NetBSD: t_snprintb.c,v 1.35 2024/04/07 15:20:17 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, 2024\
  The NetBSD Foundation, inc. All rights reserved.");
-__RCSID("$NetBSD: t_snprintb.c,v 1.34 2024/04/07 12:05:23 rillig Exp $");
+__RCSID("$NetBSD: t_snprintb.c,v 1.35 2024/04/07 15:20:17 rillig Exp $");
 
 #include <stdio.h>
 #include <string.h>
@@ -309,16 +309,16 @@ ATF_TC_BODY(snprintb, tc)
 
 	// old style, empty description
 	//
-	// Empty descriptions result in multiple commas in a row, which is a
-	// mistake.
-	h_snprintb(
+	// The description of a bit in the old format must not be empty,
+	// to prevent multiple commas in a row.
+	h_snprintb_val_error(
 	    "\020"
 	    "\001lsb"
 	    "\004"
 	    "\005"
 	    "\010msb",
 	    0xff,
-	    "0xff<lsb,,,msb>");
+	    "0xff<lsb#");
 
 	// old style, buffer size 0, null buffer
 	//
@@ -679,8 +679,8 @@ ATF_TC_BODY(snprintb, tc)
 	// new style bit-field, 'F' with non-exhaustive ':'
 	//
 	// A bit-field that does not match any values generates multiple commas
-	// in a row, which looks confusing. The ':' directives should either be
-	// exhaustive, or there should be a '*' catch-all directive.
+	// in a row, which looks confusing. The ':' conversions should either be
+	// exhaustive, or there should be a '*' catch-all conversion.
 	h_snprintb(
 	    "\177\020"
 	    "b\000bit0\0"
@@ -741,7 +741,7 @@ ATF_TC_BODY(snprintb, tc)
 
 	// new style bit-field, difference between '=' and ':'
 	//
-	// The ':' directive can almost emulate the '=' directive, without the
+	// The ':' conversion can almost emulate the '=' conversion, without the
 	// numeric output and with a different separator. It's best to use
 	// either 'f' with '=', or 'F' with ':', but not mix them.
 	h_snprintb(
@@ -757,9 +757,9 @@ ATF_TC_BODY(snprintb, tc)
 
 	// new style bit-field default, fixed string
 	//
-	// The 'f' directive pairs up with the '=' directive,
-	// the 'F' directive pairs up with the ':' directive,
-	// but there's only one 'default' directive for both variants,
+	// The 'f' conversion pairs up with the '=' conversion,
+	// the 'F' conversion pairs up with the ':' conversion,
+	// but there's only one 'default' conversion for both variants,
 	// so its description should include the '=' when used with 'f' but
 	// not with 'F'.
 	h_snprintb(
@@ -787,7 +787,7 @@ ATF_TC_BODY(snprintb, tc)
 
 	// new style bit-field default, can never match
 	//
-	// The '=' directive are exhaustive, making the '*' redundant.
+	// The '=' conversion are exhaustive, making the '*' redundant.
 	h_snprintb(
 	    "\177\020"
 	    "f\010\002f\0"
@@ -811,14 +811,14 @@ ATF_TC_BODY(snprintb, tc)
 	    0xff,
 	    "0xff<f=0xff=000000000000000000000000000255%>");
 
-	// new style unknown directive, at the beginning
+	// new style unknown conversion, at the beginning
 	h_snprintb_val_error(
 	    "\177\020"
 	    "unknown\0",
 	    0xff,
 	    "0xff#");
 
-	// new style unknown directive, after a known directive
+	// new style unknown conversion, after a known conversion
 	h_snprintb_val_error(
 	    "\177\020"
 	    "b\007msb\0"
@@ -946,42 +946,51 @@ ATF_TC_BODY(snprintb, tc)
 
 	// new style combinations, 'f' '*' '='
 	//
-	// After a catch-all '*' directive, any following '=' directive
-	// generates misleading output, which is a mistake.
-	h_snprintb(
+	// After a catch-all '*' conversions, there must not be further '='
+	// conversions.
+	h_snprintb_val_error(
 	    "\177\020"
 	    "f\000\010f\0"
 		"*=default\0"
 		"=\245match\0",
 	    0xa5,
-	    "0xa5<f=0xa5=default=match>");
+	    "0xa5<f=0xa5=default#");
 
 	// new style combinations, 'F' '*' ':'
 	//
-	// After a catch-all '*' directive, any following ':' directive
-	// generates misleading output, which is a mistake.
-	h_snprintb(
+	// After a catch-all '*' conversion, there must not be further ':'
+	// conversions.
+	h_snprintb_val_error(
 	    "\177\020"
 	    "F\000\010F\0"
 		"*default\0"
 		":\245-match\0",
 	    0xa5,
-	    "0xa5<default-match>");
+	    "0xa5<default#");
 
-	// new style combinations, '*' '*'
+	// new style combinations, 'f' '*' '*'
 	//
-	// After a catch-all '*' directive, any further '*' directive is
-	// ignored and thus redundant, which is a mistake.
-	h_snprintb(
+	// After a catch-all '*' conversion, there must not be further '=' or
+	// '*' conversions.
+	h_snprintb_val_error(
 	    "\177\020"
 	    "f\000\010f\0"
 		"*=default-f\0"
-		"*ignored\0"
+		"*ignored\0",
+	    0xa5,
+	    "0xa5<f=0xa5=default-f#");
+
+	// new style combinations, 'F' '*' '*'
+	//
+	// After a catch-all '*' conversion, there must not be further ':' or
+	// '*' conversions.
+	h_snprintb_val_error(
+	    "\177\020"
 	    "F\000\010\0"
 		"*default-F\0"
 		"*ignored\0",
 	    0xa5,
-	    "0xa5<f=0xa5=default-f,default-F>");
+	    "0xa5<default-F#");
 
 	// example from the manual page, old style octal
 	h_snprintb(

Reply via email to