[backfire] package/busybox: add patch missing from r29315 (oops)
[openwrt/svn-archive/archive.git] / package / busybox / patches / 004-upstream-percent_decode_in_place.patch
1 --- a/include/libbb.h
2 +++ b/include/libbb.h
3 @@ -1368,6 +1368,15 @@ pid_t *find_pid_by_name(const char* proc
4 pid_t *pidlist_reverse(pid_t *pidList) FAST_FUNC;
5
6
7 +/* Use strict=1 if you process input from untrusted source:
8 + * it will return NULL on invalid %xx (bad hex chars)
9 + * and str + 1 if decoded char is / or NUL.
10 + * In non-strict mode, it always succeeds (returns str),
11 + * and also it additionally decoded '+' to space.
12 + */
13 +char *percent_decode_in_place(char *str, int strict) FAST_FUNC;
14 +
15 +
16 extern const char bb_uuenc_tbl_base64[];
17 extern const char bb_uuenc_tbl_std[];
18 void bb_uuencode(char *store, const void *s, int length, const char *tbl) FAST_FUNC;
19 --- a/libbb/Kbuild
20 +++ b/libbb/Kbuild
21 @@ -66,6 +66,7 @@ lib-y += mtab_file.o
22 lib-y += obscure.o
23 lib-y += parse_mode.o
24 lib-y += parse_config.o
25 +lib-y += percent_decode.o
26 lib-y += perror_msg.o
27 lib-y += perror_msg_and_die.o
28 lib-y += perror_nomsg.o
29 --- /dev/null
30 +++ b/libbb/percent_decode.c
31 @@ -0,0 +1,69 @@
32 +/* vi: set sw=4 ts=4: */
33 +/*
34 + * Licensed under GPLv2 or later, see file LICENSE in this source tree.
35 + */
36 +
37 +//kbuild:lib-y += percent_decode.o
38 +
39 +#include "libbb.h"
40 +
41 +static unsigned hex_to_bin(unsigned char c)
42 +{
43 + unsigned v;
44 +
45 + v = c - '0';
46 + if (v <= 9)
47 + return v;
48 + /* c | 0x20: letters to lower case, non-letters
49 + * to (potentially different) non-letters */
50 + v = (unsigned)(c | 0x20) - 'a';
51 + if (v <= 5)
52 + return v + 10;
53 + return ~0;
54 +/* For testing:
55 +void t(char c) { printf("'%c'(%u) %u\n", c, c, hex_to_bin(c)); }
56 +int main() { t(0x10); t(0x20); t('0'); t('9'); t('A'); t('F'); t('a'); t('f');
57 +t('0'-1); t('9'+1); t('A'-1); t('F'+1); t('a'-1); t('f'+1); return 0; }
58 +*/
59 +}
60 +
61 +char* FAST_FUNC percent_decode_in_place(char *str, int strict)
62 +{
63 + /* note that decoded string is always shorter than original */
64 + char *src = str;
65 + char *dst = str;
66 + char c;
67 +
68 + while ((c = *src++) != '\0') {
69 + unsigned v;
70 +
71 + if (!strict && c == '+') {
72 + *dst++ = ' ';
73 + continue;
74 + }
75 + if (c != '%') {
76 + *dst++ = c;
77 + continue;
78 + }
79 + v = hex_to_bin(src[0]);
80 + if (v > 15) {
81 + bad_hex:
82 + if (strict)
83 + return NULL;
84 + *dst++ = '%';
85 + continue;
86 + }
87 + v = (v * 16) | hex_to_bin(src[1]);
88 + if (v > 255)
89 + goto bad_hex;
90 + if (strict && (v == '/' || v == '\0')) {
91 + /* caller takes it as indication of invalid
92 + * (dangerous wrt exploits) chars */
93 + return str + 1;
94 + }
95 + *dst++ = v;
96 + src += 2;
97 + }
98 + *dst = '\0';
99 + return str;
100 +}
101 --- a/networking/httpd.c
102 +++ b/networking/httpd.c
103 @@ -785,78 +785,6 @@ static char *encodeString(const char *st
104 }
105 #endif /* FEATURE_HTTPD_ENCODE_URL_STR */
106
107 -/*
108 - * Given a URL encoded string, convert it to plain ascii.
109 - * Since decoding always makes strings smaller, the decode is done in-place.
110 - * Thus, callers should xstrdup() the argument if they do not want the
111 - * argument modified. The return is the original pointer, allowing this
112 - * function to be easily used as arguments to other functions.
113 - *
114 - * string The first string to decode.
115 - * option_d 1 if called for httpd -d
116 - *
117 - * Returns a pointer to the decoded string (same as input).
118 - */
119 -static unsigned hex_to_bin(unsigned char c)
120 -{
121 - unsigned v;
122 -
123 - v = c - '0';
124 - if (v <= 9)
125 - return v;
126 - /* c | 0x20: letters to lower case, non-letters
127 - * to (potentially different) non-letters */
128 - v = (unsigned)(c | 0x20) - 'a';
129 - if (v <= 5)
130 - return v + 10;
131 - return ~0;
132 -}
133 -/* For testing:
134 -void t(char c) { printf("'%c'(%u) %u\n", c, c, hex_to_bin(c)); }
135 -int main() { t(0x10); t(0x20); t('0'); t('9'); t('A'); t('F'); t('a'); t('f');
136 -t('0'-1); t('9'+1); t('A'-1); t('F'+1); t('a'-1); t('f'+1); return 0; }
137 -*/
138 -static char *decodeString(char *orig, int option_d)
139 -{
140 - /* note that decoded string is always shorter than original */
141 - char *string = orig;
142 - char *ptr = string;
143 - char c;
144 -
145 - while ((c = *ptr++) != '\0') {
146 - unsigned v;
147 -
148 - if (option_d && c == '+') {
149 - *string++ = ' ';
150 - continue;
151 - }
152 - if (c != '%') {
153 - *string++ = c;
154 - continue;
155 - }
156 - v = hex_to_bin(ptr[0]);
157 - if (v > 15) {
158 - bad_hex:
159 - if (!option_d)
160 - return NULL;
161 - *string++ = '%';
162 - continue;
163 - }
164 - v = (v * 16) | hex_to_bin(ptr[1]);
165 - if (v > 255)
166 - goto bad_hex;
167 - if (!option_d && (v == '/' || v == '\0')) {
168 - /* caller takes it as indication of invalid
169 - * (dangerous wrt exploits) chars */
170 - return orig + 1;
171 - }
172 - *string++ = v;
173 - ptr += 2;
174 - }
175 - *string = '\0';
176 - return orig;
177 -}
178 -
179 #if ENABLE_FEATURE_HTTPD_BASIC_AUTH
180 /*
181 * Decode a base64 data stream as per rfc1521.
182 @@ -1876,7 +1804,7 @@ static void handle_incoming_and_exit(con
183 }
184
185 /* Decode URL escape sequences */
186 - tptr = decodeString(urlcopy, 0);
187 + tptr = percent_decode_in_place(urlcopy, /*strict:*/ 1);
188 if (tptr == NULL)
189 send_headers_and_exit(HTTP_BAD_REQUEST);
190 if (tptr == urlcopy + 1) {
191 @@ -2319,7 +2247,7 @@ int httpd_main(int argc UNUSED_PARAM, ch
192 , &verbose
193 );
194 if (opt & OPT_DECODE_URL) {
195 - fputs(decodeString(url_for_decode, 1), stdout);
196 + fputs(percent_decode_in_place(url_for_decode, /*strict:*/ 0), stdout);
197 return 0;
198 }
199 #if ENABLE_FEATURE_HTTPD_ENCODE_URL_STR
200 --- a/networking/wget.c
201 +++ b/networking/wget.c
202 @@ -373,8 +373,13 @@ static void parse_url(char *src_url, str
203 sp = strrchr(h->host, '@');
204 h->user = NULL;
205 if (sp != NULL) {
206 - h->user = h->host;
207 + // URL-decode "user:password" string before base64-encoding:
208 + // wget http://test:my%20pass@example.com should send
209 + // Authorization: Basic dGVzdDpteSBwYXNz
210 + // which decodes to "test:my pass".
211 + // Standard wget and curl do this too.
212 *sp = '\0';
213 + h->user = percent_decode_in_place(h->host, /*strict:*/ 0);
214 h->host = sp + 1;
215 }
216