Inconsistent behavior with dd(1)

From: William Orr <will_at_worrbase.com>
Date: Thu, 14 Aug 2014 22:55:25 -0700
Hey,

I found some inconsistent behavior with dd(1) when it comes to specifying arguments in -CURRENT.

 [ worr on terra ] ( ~ ) % dd if=/dev/zero of=/dev/null count=18446744073709551616
dd: count: Result too large
 [ worr on terra ] ( ~ ) % dd if=/dev/zero of=/dev/null count=18446744073709551617
dd: count: Result too large
 [ worr on terra ] ( ~ ) % dd if=/dev/zero of=/dev/null count=18446744073709551615
dd: count cannot be negative
 [ worr on terra ] ( ~ ) % dd if=/dev/zero of=/dev/null count=-18446744073709551615
1+0 records in
1+0 records out
512 bytes transferred in 0.000373 secs (1373071 bytes/sec)
 [ worr on terra ] ( ~ ) % dd if=/dev/zero of=/dev/null count=-1
dd: count cannot be negative

—

Any chance someone has the time and could take a look? https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=191263

Thanks,
William Orr

—

Here’s the patch:

Index: bin/dd/args.c
===================================================================
--- bin/dd/args.c	(revision 267712)
+++ bin/dd/args.c	(working copy)
_at__at_ -186,46 +186,31 _at__at_
 static void
 f_bs(char *arg)
 {
-	uintmax_t res;
-
-	res = get_num(arg);
-	if (res < 1 || res > SSIZE_MAX)
-		errx(1, "bs must be between 1 and %jd", (intmax_t)SSIZE_MAX);
-	in.dbsz = out.dbsz = (size_t)res;
+	in.dbsz = out.dbsz = get_num(arg);
+	if (in.dbsz < 1 || out.dbsz < 1)
+		errx(1, "bs must be between 1 and %ju", (uintmax_t)-1);
 }
 
 static void
 f_cbs(char *arg)
 {
-	uintmax_t res;
-
-	res = get_num(arg);
-	if (res < 1 || res > SSIZE_MAX)
-		errx(1, "cbs must be between 1 and %jd", (intmax_t)SSIZE_MAX);
-	cbsz = (size_t)res;
+	cbsz = get_num(arg);
+	if (cbsz < 1)
+		errx(1, "cbs must be between 1 and %ju", (uintmax_t)-1);
 }
 
 static void
 f_count(char *arg)
 {
-	intmax_t res;
-
-	res = (intmax_t)get_num(arg);
-	if (res < 0)
-		errx(1, "count cannot be negative");
-	if (res == 0)
-		cpy_cnt = (uintmax_t)-1;
-	else
-		cpy_cnt = (uintmax_t)res;
+	cpy_cnt = get_num(arg);
 }
 
 static void
 f_files(char *arg)
 {
-
 	files_cnt = get_num(arg);
 	if (files_cnt < 1)
-		errx(1, "files must be between 1 and %jd", (uintmax_t)-1);
+		errx(1, "files must be between 1 and %ju", (uintmax_t)-1);
 }
 
 static void
_at__at_ -241,14 +226,10 _at__at_
 static void
 f_ibs(char *arg)
 {
-	uintmax_t res;
-
 	if (!(ddflags & C_BS)) {
-		res = get_num(arg);
-		if (res < 1 || res > SSIZE_MAX)
-			errx(1, "ibs must be between 1 and %jd",
-			    (intmax_t)SSIZE_MAX);
-		in.dbsz = (size_t)res;
+		in.dbsz = get_num(arg);
+		if (in.dbsz < 1)
+			errx(1, "ibs must be between 1 and %ju", (uintmax_t)-1);
 	}
 }
 
_at__at_ -262,14 +243,10 _at__at_
 static void
 f_obs(char *arg)
 {
-	uintmax_t res;
-
 	if (!(ddflags & C_BS)) {
-		res = get_num(arg);
-		if (res < 1 || res > SSIZE_MAX)
-			errx(1, "obs must be between 1 and %jd",
-			    (intmax_t)SSIZE_MAX);
-		out.dbsz = (size_t)res;
+		out.dbsz = get_num(arg);
+		if (out.dbsz < 1)
+			errx(1, "obs must be between 1 and %ju", (uintmax_t)-1);
 	}
 }
 
_at__at_ -378,11 +355,14 _at__at_
 	uintmax_t num, mult, prevnum;
 	char *expr;
 
+	if (val[0] == '-')
+		errx(1, "%s: cannot be negative", oper);
+
 	errno = 0;
 	num = strtouq(val, &expr, 0);
 	if (errno != 0)				/* Overflow or underflow. */
 		err(1, "%s", oper);
-	
+
 	if (expr == val)			/* No valid digits. */
 		errx(1, "%s: illegal numeric value", oper);
 
Index: bin/dd/dd.c
===================================================================
--- bin/dd/dd.c	(revision 267712)
+++ bin/dd/dd.c	(working copy)
_at__at_ -284,8 +284,6 _at__at_
 
 	for (;;) {
 		switch (cpy_cnt) {
-		case -1:			/* count=0 was specified */
-			return;
 		case 0:
 			break;
 		default:



Received on Fri Aug 15 2014 - 04:02:24 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:40:51 UTC