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;
}
}