Hi,
Currently, jot(1) restricts arguments given to the `-s', `-b' and `-w'
options to BUFSIZ characters; this is a typical misuse of that constant,
which has essentially nothing to do with the expected maximum size of
argv's elements. Besides, I have actually hit this limit multiple times
recently, so I decided to fix it.
In the case of `-s', this was trivial.
In the case of `-b' and `-w', the quick and dirty solution would have
been to declare a larger `format' buffer, but the proper way is to
allocate the required length dynamically, as shown below.
Index: jot.c
===================================================================
RCS file: /cvs/src/usr.bin/jot/jot.c,v
retrieving revision 1.41
diff -u -p -r1.41 jot.c
--- jot.c 30 Dec 2017 07:21:10 -0000 1.41
+++ jot.c 31 Dec 2017 13:50:59 -0000
@@ -59,8 +59,8 @@ static double begin = 1;
static double ender = 100;
static double step = 1;
-static char format[BUFSIZ];
-static char sepstring[BUFSIZ] = "\n";
+static char *format = NULL;
+static char *sepstring = "\n";
static int prec = -1;
static bool boring;
static bool chardata;
@@ -85,7 +85,7 @@ main(int argc, char *argv[])
unsigned int mask = 0;
int n = 0;
int ch;
- const char *errstr;
+ const char *errstr;
if (pledge("stdio", NULL) == -1)
err(1, "pledge");
@@ -94,9 +94,9 @@ main(int argc, char *argv[])
switch (ch) {
case 'b':
boring = true;
- if (strlcpy(format, optarg, sizeof(format)) >=
- sizeof(format))
- errx(1, "-b word too long");
+ free(format);
+ if ((format = strdup(optarg)) == NULL)
+ err(1, NULL);
break;
case 'c':
chardata = true;
@@ -114,14 +114,12 @@ main(int argc, char *argv[])
randomize = true;
break;
case 's':
- if (strlcpy(sepstring, optarg, sizeof(sepstring)) >=
- sizeof(sepstring))
- errx(1, "-s string too long");
+ sepstring = optarg;
break;
case 'w':
- if (strlcpy(format, optarg, sizeof(format)) >=
- sizeof(format))
- errx(1, "-w word too long");
+ free(format);
+ if ((format = strdup(optarg)) == NULL)
+ err(1, NULL);
break;
default:
usage();
@@ -176,7 +174,8 @@ main(int argc, char *argv[])
argv[4]);
}
- getformat();
+ if (!boring)
+ getformat();
if (!randomize) {
/*
@@ -356,32 +355,29 @@ static void
getformat(void)
{
char *p, *p2;
- int dot, hash, space, sign, numbers = 0;
- size_t sz;
+ int n, dot, hash, space, sign, numbers;
+ size_t len = 0;
- if (boring) /* no need to bother */
- return;
- for (p = format; *p != '\0'; p++) /* look for '%' */
- if (*p == '%') {
- if (*(p+1) != '%')
- break;
- p++; /* leave %% alone */
- }
- sz = sizeof(format) - strlen(format) - 1;
- if (*p == '\0' && !chardata) {
- int n;
-
- n = snprintf(p, sz, "%%.%df", prec);
- if (n == -1 || n >= (int)sz)
- errx(1, "-w word too long");
- } else if (*p == '\0' && chardata) {
- if (strlcpy(p, "%c", sz) >= sz)
- errx(1, "-w word too long");
+ if ((p = format) != NULL) {
+ while ((p = strchr(p, '%')) != NULL && p[1] == '%')
+ p += 2;
+ len = strlen(format);
+ }
+ if (p == NULL && !chardata) {
+ if ((n = snprintf(NULL, 0, "%%.%df", prec)) == -1 ||
+ (format = realloc(format, len + n + 1)) == NULL ||
+ snprintf(format + len, n + 1, "%%.%df", prec) != n)
+ err(1, NULL);
+ } else if (p == NULL && chardata) {
+ if ((format = realloc(format, len + sizeof("%c"))) == NULL)
+ err(1, NULL);
+ strcpy(format + len, "%c");
intdata = true;
} else if (*(p+1) == '\0') {
/* cannot end in single '%' */
- if (strlcat(format, "%", sizeof(format)) >= sizeof(format))
- errx(1, "-w word too long");
+ if ((format = realloc(format, len + sizeof("%"))) == NULL)
+ err(1, NULL);
+ strcpy(format + len, "%");
} else {
/*
* Allow conversion format specifiers of the form
@@ -456,9 +452,10 @@ fmt_broken:
p++;
else if (*p == '%' && *(p+1) == '\0') {
/* cannot end in single '%' */
- if (strlcat(format, "%", sizeof(format)) >=
- sizeof(format))
- errx(1, "-w word too long");
+ if ((format = realloc(format,
+ len + sizeof("%"))) == NULL)
+ err(1, NULL);
+ strcpy(format + len, "%");
break;
}
}
Regards,
kshe