diff options
-rw-r--r-- | libbb/process_escape_sequence.c | 64 |
1 files changed, 43 insertions, 21 deletions
diff --git a/libbb/process_escape_sequence.c b/libbb/process_escape_sequence.c index 9b57ff99e..28b1e3697 100644 --- a/libbb/process_escape_sequence.c +++ b/libbb/process_escape_sequence.c | |||
@@ -22,48 +22,69 @@ | |||
22 | * | 22 | * |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <string.h> | ||
26 | #include <stdio.h> | 25 | #include <stdio.h> |
27 | #include <limits.h> | 26 | #include <limits.h> |
28 | #include <ctype.h> | 27 | #include <ctype.h> |
29 | #include "libbb.h" | 28 | #include "libbb.h" |
30 | 29 | ||
31 | #define isodigit(c) ((c) >= '0' && (c) <= '7') | 30 | #define WANT_HEX_ESCAPES 1 |
32 | #define hextobin(c) ((c)>='a'&&(c)<='f' ? (c)-'a'+10 : (c)>='A'&&(c)<='F' ? (c)-'A'+10 : (c)-'0') | 31 | |
33 | #define octtobin(c) ((c) - '0') | 32 | /* Usual "this only works for ascii compatible encodings" disclaimer. */ |
33 | #undef _tolower | ||
34 | #define _tolower(X) ((X)|((char) 0x20)) | ||
35 | |||
34 | char bb_process_escape_sequence(const char **ptr) | 36 | char bb_process_escape_sequence(const char **ptr) |
35 | { | 37 | { |
36 | const char *p, *q; | ||
37 | unsigned int num_digits, r, n, hexescape; | ||
38 | static const char charmap[] = { | 38 | static const char charmap[] = { |
39 | 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', 0, | 39 | 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', 0, |
40 | '\a', '\b', '\f', '\n', '\r', '\t', '\v', '\\', '\\' }; | 40 | '\a', '\b', '\f', '\n', '\r', '\t', '\v', '\\', '\\' }; |
41 | 41 | ||
42 | n = r = hexescape = num_digits = 0; | 42 | const char *p; |
43 | const char *q; | ||
44 | unsigned int num_digits; | ||
45 | unsigned int r; | ||
46 | unsigned int n; | ||
47 | unsigned int d; | ||
48 | unsigned int base; | ||
49 | |||
50 | num_digits = n = 0; | ||
51 | base = 8; | ||
43 | q = *ptr; | 52 | q = *ptr; |
44 | 53 | ||
54 | #ifdef WANT_HEX_ESCAPES | ||
45 | if (*q == 'x') { | 55 | if (*q == 'x') { |
46 | hexescape++; | ||
47 | ++q; | 56 | ++q; |
57 | base = 16; | ||
58 | ++num_digits; | ||
48 | } | 59 | } |
60 | #endif | ||
49 | 61 | ||
50 | do { | 62 | do { |
51 | if (hexescape && isxdigit(*q)) { | 63 | d = (unsigned int)(*q - '0'); |
52 | r = n * 16 + hextobin(*q); | 64 | #ifdef WANT_HEX_ESCAPES |
53 | } else if (isodigit(*q)) { | 65 | if (d >= 10) { |
54 | r = n * 8 + octtobin(*q); | 66 | d = ((unsigned int)(_tolower(*q) - 'a')) + 10; |
55 | } else { | ||
56 | break; | ||
57 | } | 67 | } |
58 | if (r <= UCHAR_MAX) { | 68 | #endif |
59 | n = r; | 69 | |
60 | ++q; | 70 | if (d >= base) { |
61 | if (++num_digits < 3) { | 71 | #ifdef WANT_HEX_ESCAPES |
62 | continue; | 72 | if ((base == 16) && (!--num_digits)) { |
73 | /* return '\\'; */ | ||
74 | --q; | ||
63 | } | 75 | } |
76 | #endif | ||
77 | break; | ||
64 | } | 78 | } |
65 | break; | 79 | |
66 | } while (1); | 80 | r = n * base + d; |
81 | if (r > UCHAR_MAX) { | ||
82 | break; | ||
83 | } | ||
84 | |||
85 | n = r; | ||
86 | ++q; | ||
87 | } while (++num_digits < 3); | ||
67 | 88 | ||
68 | if (num_digits == 0) { /* mnemonic escape sequence? */ | 89 | if (num_digits == 0) { /* mnemonic escape sequence? */ |
69 | p = charmap; | 90 | p = charmap; |
@@ -77,6 +98,7 @@ char bb_process_escape_sequence(const char **ptr) | |||
77 | } | 98 | } |
78 | 99 | ||
79 | *ptr = q; | 100 | *ptr = q; |
101 | |||
80 | return (char) n; | 102 | return (char) n; |
81 | } | 103 | } |
82 | 104 | ||