From 495a33e6577b02362acd37ffd454c2793803fda3 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Tue, 29 Aug 2023 18:34:53 -0700 Subject: [PATCH] xxd: better error message. `xxd -r` with `-p` format input (rather than the `xxd -r -p` that you actually need to decode that) doesn't work because the input isn't in the expected
: format. "real" xxd silently outputs nothing. toybox complains about an invalid seek. This patch outputs a clear error if we don't see the leading address/offset and either ' ' or ':' as a separator (and tests for both kinds of input). Looking at the other use of scanf() in this code and testing against "real" xxd, the fact that toybox allows `-r -i` to parse input without commas actually matches (undocumented) xxd behavior, so I've just added a test for that. Bug: https://github.com/landley/toybox/issues/452 --- tests/xxd.test | 8 ++++++++ toys/other/xxd.c | 8 ++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/xxd.test b/tests/xxd.test index 3b350a46..9317e6a6 100755 --- a/tests/xxd.test +++ b/tests/xxd.test @@ -42,9 +42,17 @@ testcmd "-s" "-s 13 file1" \ testcmd "-r" "-r" "this is some text\n" "" \ ' 00000000: 7468 6973 2069 7320 736f 6d65 2074 6578 this is some tex\n00000010: 740a t.\n' +# This isn't documented, but "real" xxd supports this input format too. +testcmd "-r no colon" "-r" "this is some text\n" "" \ + ' 00000000 7468 6973 2069 7320 736f 6d65 2074 6578 this is some tex\n00000010: 740a t.\n' + toyonly testcmd "-r -i" "-ri" "this is some text\n" "" \ '0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6d, 0x65,\n 0x20, 0x74, 0x65, 0x78, 0x74, 0x0a\n' +# This isn't documented, but "real" xxd supports this input format too. +toyonly testcmd "-r -i no commas" "-ri" "this is some text\n" "" \ + '0x74 0x68 0x69 0x73 0x20 0x69 0x73 0x20 0x73 0x6f 0x6d 0x65\n 0x20 0x74 0x65 0x78 0x74 0x0a\n' + testcmd "-r garbage" '-r -' 'hello' '' '0000: 68 65 6c6c 6fxxxx\n' # -r will only read -c bytes (default 16) before skipping to the next line, diff --git a/toys/other/xxd.c b/toys/other/xxd.c index 60bdb4bc..2afa5298 100644 --- a/toys/other/xxd.c +++ b/toys/other/xxd.c @@ -123,13 +123,17 @@ static void do_xxd_reverse(int fd, char *name) if (FLAG(i)) while (fscanf(fp, " 0x%02x,", &tmp) == 1) xputc(tmp); else while (!feof(fp)) { int col = 0; + char ch; // Each line of a regular hexdump starts with an offset/address. // Each line of a plain hexdump just goes straight into the bytes. - if (!FLAG(p) && fscanf(fp, "%llx: ", &pos) == 1) { + if (!FLAG(p) && fscanf(fp, "%llx%c ", &pos, &ch) == 2) { + if (ch != ':' && ch != ' ') + error_exit("%s: no separator between offset/address and bytes " + "(missing -p?)", name); if (pos != current_pos && fseek(stdout, pos, SEEK_SET)) { // TODO: just write out zeros if non-seekable? - perror_exit("%s: seek failed", name); + perror_exit("%s: seek %llx failed", name, pos); } } -- 2.39.2