[git commit] dd: fail if swab is attempted on odd-sized block

Denys Vlasenko vda.linux at googlemail.com
Tue Aug 20 00:50:49 UTC 2013


commit: http://git.busybox.net/busybox/commit/?id=5b9910f0a4a1b7976c46e6f849aaa263180e5521
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 coreutils/dd.c |   31 +++++++++++++++++++++----------
 1 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/coreutils/dd.c b/coreutils/dd.c
index d6aa5ef..e229388 100644
--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -151,13 +151,13 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
 	enum {
 		/* Must be in the same order as OP_conv_XXX! */
 		/* (see "flags |= (1 << what)" below) */
-		FLAG_NOTRUNC = 1 << 0,
-		FLAG_SYNC    = 1 << 1,
-		FLAG_NOERROR = 1 << 2,
-		FLAG_FSYNC   = 1 << 3,
-		FLAG_SWAB    = 1 << 4,
+		FLAG_NOTRUNC = (1 << 0) * ENABLE_FEATURE_DD_IBS_OBS,
+		FLAG_SYNC    = (1 << 1) * ENABLE_FEATURE_DD_IBS_OBS,
+		FLAG_NOERROR = (1 << 2) * ENABLE_FEATURE_DD_IBS_OBS,
+		FLAG_FSYNC   = (1 << 3) * ENABLE_FEATURE_DD_IBS_OBS,
+		FLAG_SWAB    = (1 << 4) * ENABLE_FEATURE_DD_IBS_OBS,
 		/* end of conv flags */
-		FLAG_TWOBUFS = 1 << 5,
+		FLAG_TWOBUFS = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS,
 		FLAG_COUNT   = 1 << 6,
 	};
 	static const char keywords[] ALIGN1 =
@@ -202,7 +202,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
 	//swab          swap every pair of input bytes: will abort on non-even reads
 #endif
 	};
-	int exitcode = EXIT_FAILURE;
+	smallint exitcode = EXIT_FAILURE;
 	size_t ibs = 512, obs = 512;
 	int i;
 	char *ibuf, *obuf;
@@ -210,12 +210,14 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
 	struct {
 		int flags;
 		size_t oc;
+		ssize_t prev_read_size; /* for detecting swab failure */
 		off_t count;
 		off_t seek, skip;
 		const char *infile, *outfile;
 	} Z;
 #define flags   (Z.flags  )
 #define oc      (Z.oc     )
+#define prev_read_size (Z.prev_read_size)
 #define count   (Z.count  )
 #define seek    (Z.seek   )
 #define skip    (Z.skip   )
@@ -381,14 +383,23 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
 			n = 0;
 		}
 		if (flags & FLAG_SWAB) {
-			/* If n is odd, last byte is not swapped:
+			uint16_t *p16, *end;
+
+			/* Our code allows only last read to be odd-sized */
+			if (prev_read_size & 1)
+				bb_error_msg_and_die("can't swab %lu byte buffer",
+						(unsigned long)prev_read_size);
+			prev_read_size = n;
+
+			/*
+			 * If n is odd, last byte is not swapped:
 			 *  echo -n "qwe" | dd conv=swab
 			 * prints "wqe".
 			 * The code does not handle correctly odd-sized reads
 			 * in the *middle* of the input. FIXME.
 			 */
-			uint16_t *p16 = (void*) ibuf;
-			uint16_t *end = (void*) (ibuf + (n & ~(ssize_t)1));
+			p16 = (void*) ibuf;
+			end = (void*) (ibuf + (n & ~(ssize_t)1));
 			while (p16 < end) {
 				*p16 = bswap_16(*p16);
 				p16++;


More information about the busybox-cvs mailing list