dd: fail if swab is attempted on odd-sized block

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2013-08-20 02:50:49 +02:00
parent e66a56de23
commit 5b9910f0a4

View File

@ -151,13 +151,13 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
enum { enum {
/* Must be in the same order as OP_conv_XXX! */ /* Must be in the same order as OP_conv_XXX! */
/* (see "flags |= (1 << what)" below) */ /* (see "flags |= (1 << what)" below) */
FLAG_NOTRUNC = 1 << 0, FLAG_NOTRUNC = (1 << 0) * ENABLE_FEATURE_DD_IBS_OBS,
FLAG_SYNC = 1 << 1, FLAG_SYNC = (1 << 1) * ENABLE_FEATURE_DD_IBS_OBS,
FLAG_NOERROR = 1 << 2, FLAG_NOERROR = (1 << 2) * ENABLE_FEATURE_DD_IBS_OBS,
FLAG_FSYNC = 1 << 3, FLAG_FSYNC = (1 << 3) * ENABLE_FEATURE_DD_IBS_OBS,
FLAG_SWAB = 1 << 4, FLAG_SWAB = (1 << 4) * ENABLE_FEATURE_DD_IBS_OBS,
/* end of conv flags */ /* end of conv flags */
FLAG_TWOBUFS = 1 << 5, FLAG_TWOBUFS = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS,
FLAG_COUNT = 1 << 6, FLAG_COUNT = 1 << 6,
}; };
static const char keywords[] ALIGN1 = 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 //swab swap every pair of input bytes: will abort on non-even reads
#endif #endif
}; };
int exitcode = EXIT_FAILURE; smallint exitcode = EXIT_FAILURE;
size_t ibs = 512, obs = 512; size_t ibs = 512, obs = 512;
int i; int i;
char *ibuf, *obuf; char *ibuf, *obuf;
@ -210,12 +210,14 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
struct { struct {
int flags; int flags;
size_t oc; size_t oc;
ssize_t prev_read_size; /* for detecting swab failure */
off_t count; off_t count;
off_t seek, skip; off_t seek, skip;
const char *infile, *outfile; const char *infile, *outfile;
} Z; } Z;
#define flags (Z.flags ) #define flags (Z.flags )
#define oc (Z.oc ) #define oc (Z.oc )
#define prev_read_size (Z.prev_read_size)
#define count (Z.count ) #define count (Z.count )
#define seek (Z.seek ) #define seek (Z.seek )
#define skip (Z.skip ) #define skip (Z.skip )
@ -381,14 +383,23 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
n = 0; n = 0;
} }
if (flags & FLAG_SWAB) { 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 * echo -n "qwe" | dd conv=swab
* prints "wqe". * prints "wqe".
* The code does not handle correctly odd-sized reads * The code does not handle correctly odd-sized reads
* in the *middle* of the input. FIXME. * in the *middle* of the input. FIXME.
*/ */
uint16_t *p16 = (void*) ibuf; p16 = (void*) ibuf;
uint16_t *end = (void*) (ibuf + (n & ~(ssize_t)1)); end = (void*) (ibuf + (n & ~(ssize_t)1));
while (p16 < end) { while (p16 < end) {
*p16 = bswap_16(*p16); *p16 = bswap_16(*p16);
p16++; p16++;