Module Name:    src
Committed By:   rillig
Date:           Fri Feb 16 19:20:38 UTC 2024

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

Log Message:
snprintb: fix integer overflow when writing past a small buffer

Previously, snprintb returned -1 in this case, assuming that the
snprintf used in FMTSTR validates against an overly large buffer size.


To generate a diff of this commit:
cvs rdiff -u -r1.30 -r1.31 src/common/lib/libutil/snprintb.c
cvs rdiff -u -r1.18 -r1.19 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.30 src/common/lib/libutil/snprintb.c:1.31
--- src/common/lib/libutil/snprintb.c:1.30	Fri Feb 16 18:17:10 2024
+++ src/common/lib/libutil/snprintb.c	Fri Feb 16 19:20:38 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: snprintb.c,v 1.30 2024/02/16 18:17:10 rillig Exp $	*/
+/*	$NetBSD: snprintb.c,v 1.31 2024/02/16 19:20:38 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.30 2024/02/16 18:17:10 rillig Exp $");
+__RCSID("$NetBSD: snprintb.c,v 1.31 2024/02/16 19:20:38 rillig Exp $");
 #  endif
 
 #  include <sys/types.h>
@@ -51,7 +51,7 @@ __RCSID("$NetBSD: snprintb.c,v 1.30 2024
 #  include <errno.h>
 # else /* ! _KERNEL */
 #  include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: snprintb.c,v 1.30 2024/02/16 18:17:10 rillig Exp $");
+__KERNEL_RCSID(0, "$NetBSD: snprintb.c,v 1.31 2024/02/16 19:20:38 rillig Exp $");
 #  include <sys/param.h>
 #  include <sys/inttypes.h>
 #  include <sys/systm.h>
@@ -171,8 +171,9 @@ snprintb_m(char *buf, size_t bufsize, co
 	} while (0)
 
 #define	FMTSTR(sb, f) do {						\
-		int fmt_len = snprintf(bp, bufsize - total_len, sb,	\
-		    (uintmax_t)f);					\
+		size_t n = (size_t)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;					\

Index: src/tests/lib/libutil/t_snprintb.c
diff -u src/tests/lib/libutil/t_snprintb.c:1.18 src/tests/lib/libutil/t_snprintb.c:1.19
--- src/tests/lib/libutil/t_snprintb.c:1.18	Fri Feb 16 18:13:47 2024
+++ src/tests/lib/libutil/t_snprintb.c	Fri Feb 16 19:20:38 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: t_snprintb.c,v 1.18 2024/02/16 18:13:47 rillig Exp $ */
+/* $NetBSD: t_snprintb.c,v 1.19 2024/02/16 19:20:38 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.18 2024/02/16 18:13:47 rillig Exp $");
+__RCSID("$NetBSD: t_snprintb.c,v 1.19 2024/02/16 19:20:38 rillig Exp $");
 
 #include <stdio.h>
 #include <string.h>
@@ -893,6 +893,32 @@ ATF_TC_BODY(snprintb_m, tc)
 	    "0xff<bits=0xf=fall\0"
 	);
 
+	// new-style format, buffer too small for numeric fallback
+	h_snprintb_m_len(
+	    20,
+	    "\177\020"
+	    "F\000\004\0"
+		"*fallback(%040jd)\0",
+	    0xff,
+	    64,
+	    57,
+	    "0xff<fallback(0000\0"
+	);
+
+	// new-style format, buffer too small for numeric fallback past buffer
+	h_snprintb_m_len(
+	    15,
+	    "\177\020"
+	    "F\000\004\0"
+		"*fallback(%010jd)\0"
+	    "F\004\004\0"
+		"*fallback(%010jd)\0",
+	    0xff,
+	    64,
+	    48,
+	    "0xff<fallback\0"
+	);
+
 	h_snprintb_m(
 	    "\177\020"
 	    "b\0LSB\0"

Reply via email to