aboutsummaryrefslogtreecommitdiff
path: root/util-linux
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2022-08-22 15:40:47 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2022-08-22 15:40:47 +0200
commitf318adaaab3288fe72cb853bf7ede56790a13182 (patch)
tree417db541833ecac1843e0c8f7534b5d23e9bb83e /util-linux
parent5a9d2b6e024e6c20d4d7b8c170985554c0df043d (diff)
downloadbusybox-w32-f318adaaab3288fe72cb853bf7ede56790a13182.tar.gz
busybox-w32-f318adaaab3288fe72cb853bf7ede56790a13182.tar.bz2
busybox-w32-f318adaaab3288fe72cb853bf7ede56790a13182.zip
xxd -r: without -p, stop at more than one whitespace, closes 14786
function old new delta xxd_main 888 1076 +188 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'util-linux')
-rw-r--r--util-linux/hexdump_xxd.c56
1 files changed, 39 insertions, 17 deletions
diff --git a/util-linux/hexdump_xxd.c b/util-linux/hexdump_xxd.c
index 4372ac770..dbda34bc5 100644
--- a/util-linux/hexdump_xxd.c
+++ b/util-linux/hexdump_xxd.c
@@ -76,12 +76,14 @@ static void reverse(unsigned opt, const char *filename)
76 76
77 fp = filename ? xfopen_for_read(filename) : stdin; 77 fp = filename ? xfopen_for_read(filename) : stdin;
78 78
79 get_new_line:
79 while ((buf = xmalloc_fgetline(fp)) != NULL) { 80 while ((buf = xmalloc_fgetline(fp)) != NULL) {
80 char *p; 81 char *p;
81 82
82 p = buf; 83 p = buf;
83 if (!(opt & OPT_p)) { 84 if (!(opt & OPT_p)) {
84 /* skip address */ 85 skip_address:
86 p = skip_whitespace(p);
85 while (isxdigit(*p)) p++; 87 while (isxdigit(*p)) p++;
86 /* NB: for xxd -r, first hex portion is address even without colon */ 88 /* NB: for xxd -r, first hex portion is address even without colon */
87 /* If it's there, skip it: */ 89 /* If it's there, skip it: */
@@ -94,36 +96,45 @@ static void reverse(unsigned opt, const char *filename)
94 /* Process hex bytes optionally separated by whitespace */ 96 /* Process hex bytes optionally separated by whitespace */
95 for (;;) { 97 for (;;) {
96 uint8_t val, c; 98 uint8_t val, c;
99 int badchar = 0;
97 nibble1: 100 nibble1:
98 p = skip_whitespace(p); 101 if (opt & OPT_p)
99 102 p = skip_whitespace(p);
100 c = *p++; 103 c = *p++;
101 if (isdigit(c)) 104 if (isdigit(c))
102 val = c - '0'; 105 val = c - '0';
103 else if ((c|0x20) >= 'a' && (c|0x20) <= 'f') 106 else if ((c|0x20) >= 'a' && (c|0x20) <= 'f')
104 val = (c|0x20) - ('a' - 10); 107 val = (c|0x20) - ('a' - 10);
105 else { 108 else {
106 /* xxd V1.10 is inconsistent here. 109 /* xxd V1.10 allows one non-hexnum char:
107 * echo -e "31 !3 0a 0a" | xxd -r -p 110 * echo -e "31 !3 0a 0a" | xxd -r -p
108 * is "10<a0>" (no <cr>) - "!" is ignored, 111 * is "10<a0>" (no <cr>) - "!" is ignored,
109 * but 112 * but stops for more than one:
110 * echo -e "31 !!343434\n30 0a" | xxd -r -p 113 * echo -e "31 !!343434\n30 0a" | xxd -r -p
111 * is "10<cr>" - "!!" drops rest of the line. 114 * is "10<cr>" - "!!" drops rest of the line.
112 * We will ignore all invalid chars: 115 * Note: this also covers whitespace chars:
116 * xxxxxxxx: 3031 3233 3435 3637 3839 3a3b 3c3d 3e3f 0123456789:;<=>?
117 * detects this ^ - skips this one space
118 * xxxxxxxx: 3031 3233 3435 3637 3839 3a3b 3c3d 3e3f 0123456789:;<=>?
119 * detects this ^^ - skips the rest
113 */ 120 */
114 if (c != '\0') 121 if (c == '\0' || badchar)
115 goto nibble1; 122 break;
116 break; 123 badchar++;
124 goto nibble1;
117 } 125 }
118 val <<= 4; 126 val <<= 4;
119 127
120 /* Works the same with xxd V1.10:
121 * echo "31 09 32 0a" | xxd -r -p
122 * echo "31 0 9 32 0a" | xxd -r -p
123 * thus allow whitespace even within the byte:
124 */
125 nibble2: 128 nibble2:
126 p = skip_whitespace(p); 129 if (opt & OPT_p) {
130 /* Works the same with xxd V1.10:
131 * echo "31 09 32 0a" | xxd -r -p
132 * echo "31 0 9 32 0a" | xxd -r -p
133 * thus allow whitespace (even multiple chars)
134 * after byte's 1st char:
135 */
136 p = skip_whitespace(p);
137 }
127 138
128 c = *p++; 139 c = *p++;
129 if (isdigit(c)) 140 if (isdigit(c))
@@ -132,7 +143,16 @@ static void reverse(unsigned opt, const char *filename)
132 val |= (c|0x20) - ('a' - 10); 143 val |= (c|0x20) - ('a' - 10);
133 else { 144 else {
134 if (c != '\0') { 145 if (c != '\0') {
135 /* "...3<not_hex_char>..." ignores both chars */ 146 /* "...3<not_hex_char>...": ignore "3",
147 * skip everything up to next hexchar or newline:
148 */
149 while (!isxdigit(*p)) {
150 if (*p == '\0') {
151 free(buf);
152 goto get_new_line;
153 }
154 p++;
155 }
136 goto nibble1; 156 goto nibble1;
137 } 157 }
138 /* Nibbles can join even through newline: 158 /* Nibbles can join even through newline:
@@ -143,10 +163,12 @@ static void reverse(unsigned opt, const char *filename)
143 p = buf = xmalloc_fgetline(fp); 163 p = buf = xmalloc_fgetline(fp);
144 if (!buf) 164 if (!buf)
145 break; 165 break;
166 if (!(opt & OPT_p)) /* -p and !-p: different behavior */
167 goto skip_address;
146 goto nibble2; 168 goto nibble2;
147 } 169 }
148 putchar(val); 170 putchar(val);
149 } 171 } /* for(;;) */
150 free(buf); 172 free(buf);
151 } 173 }
152 //fclose(fp); 174 //fclose(fp);