summaryrefslogtreecommitdiffstats
path: root/usr.bin/jot
diff options
context:
space:
mode:
authorsheldonh <sheldonh@FreeBSD.org>1999-07-22 17:11:59 +0000
committersheldonh <sheldonh@FreeBSD.org>1999-07-22 17:11:59 +0000
commita2b1df94ad3af9d024aee5d5312d143cfbd269d3 (patch)
tree924fff0acbac2c8cf455d51052bd7940cde739c5 /usr.bin/jot
parent98a98ed10e1486786c861b627220276b58eca27a (diff)
downloadFreeBSD-src-a2b1df94ad3af9d024aee5d5312d143cfbd269d3.zip
FreeBSD-src-a2b1df94ad3af9d024aee5d5312d143cfbd269d3.tar.gz
Improve printf(3) conversion specifier parsing so that silly formats
aren't allowed and the right casts can be used for printf() statements. Document the conversion specifier limitations and the fact that arithmetic overflow causes a fatal error. PR: 12611 Reported by: Frode Vatvedt Fjeld <frodef@acm.org> Reviewed by: bde
Diffstat (limited to 'usr.bin/jot')
-rw-r--r--usr.bin/jot/jot.116
-rw-r--r--usr.bin/jot/jot.c100
2 files changed, 97 insertions, 19 deletions
diff --git a/usr.bin/jot/jot.1 b/usr.bin/jot/jot.1
index da39283..d0f0ce4 100644
--- a/usr.bin/jot/jot.1
+++ b/usr.bin/jot/jot.1
@@ -30,7 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)jot.1 8.1 (Berkeley) 6/6/93
-.\" $Id$
+.\" $Id: jot.1,v 1.5 1999/07/12 20:23:37 nik Exp $
.\"
.Dd June 6, 1993
.Dt JOT 1
@@ -191,3 +191,17 @@ and to print all lines 80 characters or longer,
.Xr yes 1 ,
.Xr printf 3 ,
.Xr random 3
+.Sh BUGS
+Conversion format specifiers for
+.Xr printf 3
+are limited to those of the form
+.Dl %[#][ ][{+,-}][0-9]*[.[0-9]*]?
+where
+.Dq ?
+must be one of
+.Dl [l]{d,i,o,u,x}
+or
+.Dl {c,e,f,g,D,E,G,O,U,X}
+.Pp
+No bounds-checking is performed on numeric values, so arithmetic overflow
+will cause a fatal error.
diff --git a/usr.bin/jot/jot.c b/usr.bin/jot/jot.c
index 5b67862..7dd4261 100644
--- a/usr.bin/jot/jot.c
+++ b/usr.bin/jot/jot.c
@@ -42,7 +42,7 @@ static const char copyright[] =
static char sccsid[] = "@(#)jot.c 8.1 (Berkeley) 6/6/93";
#endif
static const char rcsid[] =
- "$Id: jot.c,v 1.8 1997/11/03 07:45:33 charnier Exp $";
+ "$Id: jot.c,v 1.9 1999/05/13 12:18:24 kris Exp $";
#endif /* not lint */
/*
@@ -75,8 +75,9 @@ int randomize;
int infinity;
int boring;
int prec;
-int dox;
+int intdata;
int chardata;
+int nosign;
int nofinalnl;
char *sepstring = "\n";
char format[BUFSIZ];
@@ -105,8 +106,7 @@ main(argc, argv)
*y = (double) arc4random() / ULONG_MAX;
putdata(*y * *x + begin, reps - *i);
}
- }
- else
+ } else
for (*i = 1, *x = begin; *i <= reps || infinity; (*i)++, *x += s)
putdata(*x, reps - *i);
if (!nofinalnl)
@@ -310,13 +310,15 @@ putdata(x, notlast)
double x;
long notlast;
{
- long d = x;
- register long *dp = &d;
if (boring) /* repeated word */
printf(format);
- else if (dox) /* scalar */
- printf(format, *dp);
+ else if (chardata) /* character representation */
+ printf(format, (int)x);
+ else if (intdata && nosign) /* scalar */
+ printf(format, (unsigned long)x);
+ else if (intdata)
+ printf(format, (long)x);
else /* real */
printf(format, x);
if (notlast != 0)
@@ -354,6 +356,8 @@ void
getformat()
{
register char *p;
+ int dot, hash, space, sign, numbers, islong = 0;
+ char *s;
if (boring) /* no need to bother */
return;
@@ -364,24 +368,84 @@ getformat()
sprintf(p, "%%.%df", prec);
else if (!*p && chardata) {
strcpy(p, "%c");
- dox = 1;
- }
- else if (!*(p+1))
+ intdata = 1;
+ } else if (!*(p+1))
strcat(format, "%"); /* cannot end in single '%' */
else {
- while (!isalpha(*p))
- p++;
+ /*
+ * Allow conversion format specifiers of the form
+ * %[#][ ][{+,-}][0-9]*[.[0-9]*]? where ? must be one of
+ * [l]{d,i,o,u,x} or {f,e,g,E,G,d,o,x,D,O,U,X,c,u}
+ */
+ s = p++;
+ dot = hash = space = sign = numbers = 0;
+ while (!isalpha(*p)) {
+ if (isdigit(*p)) {
+ numbers++;
+ p++;
+ } else if ((*p == '#' && !(numbers|dot|sign|space|
+ hash++)) ||
+ (*p == ' ' && !(numbers|dot|space++)) ||
+ ((*p == '+' || *p == '-') && !(numbers|dot|sign++))
+ || (*p == '.' && !(dot++)))
+ p++;
+ else if (*p == '$' || *p == '*')
+ errx(1, "unsupported format character %c", *p);
+ else if (*p == '\0')
+ errx(1, "missing format character");
+ else
+ errx(1, "illegal format character %c", *p);
+ }
switch (*p) {
- case 'f': case 'e': case 'g': case '%':
+ case 'l':
+ islong = 1;
+ p++;
+ /* FALLTHROUGH */
+ case 'o': case 'u': case 'x': case 'X':
+ intdata = nosign = 1;
+ break;
+ case 'd': case 'i':
+ intdata = 1;
break;
+ case 'D':
+ if (!islong) {
+ intdata = 1;
+ break;
+ }
+ case 'O': case 'U':
+ if (!islong) {
+ intdata = nosign = 1;
+ break;
+ }
+ case 'c':
+ if (!(intdata | islong)) {
+ chardata = 1;
+ break;
+ }
case 's':
errx(1, "cannot convert numeric data to strings");
break;
- /* case 'd': case 'o': case 'x': case 'D': case 'O': case 'X':
- case 'c': case 'u': */
+ case 'h': case 'n': case 'p': case 'q': case 'L':
+ case '$': case '*':
+ errx(1, "unsupported format character %c", *p);
+ /* NOTREACHED */
+ case 'f': case 'e': case 'g': case 'E': case 'G':
+ if (!islong)
+ break;
+ /* FALLTHROUGH */
default:
- dox = 1;
- break;
+ *++p = '\0';
+ errx(1, "illegal or unsupported format '%s'", s);
+ /* NOTREACHED */
}
+ while (*++p)
+ if (*p == '%' && *(p+1) && *(p+1) != '%')
+ errx(1, "too many conversions");
+ else if (*p == '%' && *(p+1) == '%')
+ p++;
+ else if (*p == '%' && !*(p+1)) {
+ strcat(format, "%");
+ break;
+ }
}
}
OpenPOWER on IntegriCloud