Module Name:    src
Committed By:   kre
Date:           Sun Nov 24 12:33:00 UTC 2024

Modified Files:
        src/usr.bin/printf: printf.c

Log Message:
Improve detection and diagnosis of invalid values for conversions.
(In particular, integer conversions contain no spaces, and must always
contain at least 1 digit, '' is not valid).


To generate a diff of this commit:
cvs rdiff -u -r1.58 -r1.59 src/usr.bin/printf/printf.c

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

Modified files:

Index: src/usr.bin/printf/printf.c
diff -u src/usr.bin/printf/printf.c:1.58 src/usr.bin/printf/printf.c:1.59
--- src/usr.bin/printf/printf.c:1.58	Wed Aug  7 15:40:03 2024
+++ src/usr.bin/printf/printf.c	Sun Nov 24 12:33:00 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: printf.c,v 1.58 2024/08/07 15:40:03 kre Exp $	*/
+/*	$NetBSD: printf.c,v 1.59 2024/11/24 12:33:00 kre Exp $	*/
 
 /*
  * Copyright (c) 1989, 1993
@@ -41,7 +41,7 @@ __COPYRIGHT("@(#) Copyright (c) 1989, 19
 #if 0
 static char sccsid[] = "@(#)printf.c	8.2 (Berkeley) 3/22/95";
 #else
-__RCSID("$NetBSD: printf.c,v 1.58 2024/08/07 15:40:03 kre Exp $");
+__RCSID("$NetBSD: printf.c,v 1.59 2024/11/24 12:33:00 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -84,9 +84,11 @@ static size_t	b_length;
 static char	*b_fmt;
 
 static int	rval;
-static char  **gargv;
+static char  ** gargv, ** firstarg;
 static int	long_double;
 
+#define	ARGNUM	((int)(gargv - firstarg))
+
 #ifdef BUILTIN		/* csh builtin */
 #define main progprintf
 #endif
@@ -124,6 +126,7 @@ static int	long_double;
 #define octtobin(c)	((c) - '0')
 #define check(c, a)	(c) >= (a) && (c) <= (a) + 5 ? (c) - (a) + 10
 #define hextobin(c)	(check(c, 'a') : check(c, 'A') : (c) - '0')
+
 #ifdef main
 int main(int, char *[]);
 #endif
@@ -199,7 +202,7 @@ main(int argc, char *argv[])
 	}
 
 	format = *argv;		/* First remaining arg is the format string */
-	gargv = ++argv;		/* remaining args are for that to consume */
+	firstarg = gargv = ++argv; /* remaining args are for that to consume */
 
 #define SKIP1	"#-+ 0'"
 #define SKIP2	"0123456789"
@@ -217,6 +220,7 @@ main(int argc, char *argv[])
 		for (fmt = format; (ch = *fmt++) != '\0';) {
 			if (ch == '\\') {
 				char c_ch;
+
 				fmt = conv_escape(fmt, &c_ch, 0);
 				putchar(c_ch);
 				continue;
@@ -409,14 +413,14 @@ main(int argc, char *argv[])
 		}
 	} while (gargv != argv && *gargv);
 
-  done:
+  done:;
 	(void)fflush(stdout);
 	if (ferror(stdout)) {
 		clearerr(stdout);
 		err(1, "write error");
 	}
 	return rval & ~0x100;
-  out:
+  out:;
 	warn("print failed");
 	return 1;
 }
@@ -482,6 +486,7 @@ conv_escape_str(char *str, void (*do_put
 		 */
 		if (ch == '0') {
 			int octnum = 0, i;
+
 			for (i = 0; i < 3; i++) {
 				if (!isdigit((unsigned char)*str) || *str > '7')
 					break;
@@ -690,6 +695,7 @@ static char *
 getstr(void)
 {
 	static char empty[] = "";
+
 	if (!*gargv)
 		return empty;
 	return *gargv++;
@@ -708,11 +714,18 @@ getwidth(void)
 
 	errno = 0;
 	val = strtoul(s, &ep, 0);
-	check_conversion(s, ep);
+	if (!isdigit(*(unsigned char *)s)) {
+		warnx("Arg %d: '%s' value for '*' width/precision"
+		    " must be an unsigned integer", ARGNUM, s);
+		rval = 1;
+		val = 0;
+	} else
+		check_conversion(s, ep);
 
 	/* Arbitrarily 'restrict' field widths to 1Mbyte */
 	if (val > 1 << 20) {
-		warnx("%s: invalid field width", s);
+		warnx("Arg %d: %s: invalid field width/precision", ARGNUM, s);
+		rval = 1;
 		return 0;
 	}
 
@@ -735,7 +748,11 @@ getintmax(void)
 
 	errno = 0;
 	val = strtoimax(cp, &ep, 0);
-	check_conversion(cp, ep);
+	if (*cp != '+' && *cp != '-' && !isdigit(*(unsigned char *)cp)) {
+		warnx("Arg %d: '%s' numeric value required", ARGNUM, cp);
+		rval = 1;
+	} else
+		check_conversion(cp, ep);
 	return val;
 }
 
@@ -780,10 +797,11 @@ wide_char(const char *p, int all)
 	(void)mbtowc(NULL, NULL, 0);
 	n = mbtowc(&wch, p + all, (len = strlen(p + all)) + 1);
 	if (n < 0) {
-		warn("%s", p);
-		rval = -1;
+		warn("Arg %d: %s", ARGNUM, p);
+		rval = 1;
 	} else if (all && (size_t)n != len) {
-		warnx("%s: not completely converted", p);
+		warnx("Arg %d: %s: not completely converted",
+		    ARGNUM, p);
 		rval = 1;
 	}
 
@@ -793,14 +811,24 @@ wide_char(const char *p, int all)
 static void
 check_conversion(const char *s, const char *ep)
 {
+	if (!*s) {
+		warnx("Arg %d: unexpected empty value ('')", ARGNUM);
+		rval = 1;
+		return;
+	}
+
 	if (*ep) {
 		if (ep == s)
-			warnx("%s: expected numeric value", s);
+			warnx("Arg %d: %s: numeric value expected", ARGNUM, s);
 		else
-			warnx("%s: not completely converted", s);
+			warnx("Arg %d: %s: not completely converted",
+			    ARGNUM, s);
 		rval = 1;
-	} else if (errno == ERANGE) {
-		warnx("%s: %s", s, strerror(ERANGE));
+		return;
+	}
+
+	if (errno == ERANGE) {
+		warnx("Arg %d: %s: %s", ARGNUM, s, strerror(ERANGE));
 		rval = 1;
 	}
 }

Reply via email to