[backfire] package/busybox: add patch missing from r29315 (oops)
authorNicolas Thill <nico@openwrt.org>
Wed, 23 Nov 2011 23:24:59 +0000 (23:24 +0000)
committerNicolas Thill <nico@openwrt.org>
Wed, 23 Nov 2011 23:24:59 +0000 (23:24 +0000)
SVN-Revision: 29322

package/busybox/patches/004-upstream-percent_decode_in_place.patch [new file with mode: 0644]

diff --git a/package/busybox/patches/004-upstream-percent_decode_in_place.patch b/package/busybox/patches/004-upstream-percent_decode_in_place.patch
new file mode 100644 (file)
index 0000000..521037d
--- /dev/null
@@ -0,0 +1,216 @@
+--- a/include/libbb.h
++++ b/include/libbb.h
+@@ -1368,6 +1368,15 @@ pid_t *find_pid_by_name(const char* proc
+ pid_t *pidlist_reverse(pid_t *pidList) FAST_FUNC;
++/* Use strict=1 if you process input from untrusted source:
++ * it will return NULL on invalid %xx (bad hex chars)
++ * and str + 1 if decoded char is / or NUL.
++ * In non-strict mode, it always succeeds (returns str),
++ * and also it additionally decoded '+' to space.
++ */
++char *percent_decode_in_place(char *str, int strict) FAST_FUNC;
++
++
+ extern const char bb_uuenc_tbl_base64[];
+ extern const char bb_uuenc_tbl_std[];
+ void bb_uuencode(char *store, const void *s, int length, const char *tbl) FAST_FUNC;
+--- a/libbb/Kbuild
++++ b/libbb/Kbuild
+@@ -66,6 +66,7 @@ lib-y += mtab_file.o
+ lib-y += obscure.o
+ lib-y += parse_mode.o
+ lib-y += parse_config.o
++lib-y += percent_decode.o
+ lib-y += perror_msg.o
+ lib-y += perror_msg_and_die.o
+ lib-y += perror_nomsg.o
+--- /dev/null
++++ b/libbb/percent_decode.c
+@@ -0,0 +1,69 @@
++/* vi: set sw=4 ts=4: */
++/*
++ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
++ */
++
++//kbuild:lib-y += percent_decode.o
++
++#include "libbb.h"
++
++static unsigned hex_to_bin(unsigned char c)
++{
++      unsigned v;
++
++      v = c - '0';
++      if (v <= 9)
++              return v;
++      /* c | 0x20: letters to lower case, non-letters
++       * to (potentially different) non-letters */
++      v = (unsigned)(c | 0x20) - 'a';
++      if (v <= 5)
++              return v + 10;
++      return ~0;
++/* For testing:
++void t(char c) { printf("'%c'(%u) %u\n", c, c, hex_to_bin(c)); }
++int main() { t(0x10); t(0x20); t('0'); t('9'); t('A'); t('F'); t('a'); t('f');
++t('0'-1); t('9'+1); t('A'-1); t('F'+1); t('a'-1); t('f'+1); return 0; }
++*/
++}
++
++char* FAST_FUNC percent_decode_in_place(char *str, int strict)
++{
++      /* note that decoded string is always shorter than original */
++      char *src = str;
++      char *dst = str;
++      char c;
++
++      while ((c = *src++) != '\0') {
++              unsigned v;
++
++              if (!strict && c == '+') {
++                      *dst++ = ' ';
++                      continue;
++              }
++              if (c != '%') {
++                      *dst++ = c;
++                      continue;
++              }
++              v = hex_to_bin(src[0]);
++              if (v > 15) {
++ bad_hex:
++                      if (strict)
++                              return NULL;
++                      *dst++ = '%';
++                      continue;
++              }
++              v = (v * 16) | hex_to_bin(src[1]);
++              if (v > 255)
++                      goto bad_hex;
++              if (strict && (v == '/' || v == '\0')) {
++                      /* caller takes it as indication of invalid
++                       * (dangerous wrt exploits) chars */
++                      return str + 1;
++              }
++              *dst++ = v;
++              src += 2;
++      }
++      *dst = '\0';
++      return str;
++}
+--- a/networking/httpd.c
++++ b/networking/httpd.c
+@@ -785,78 +785,6 @@ static char *encodeString(const char *st
+ }
+ #endif          /* FEATURE_HTTPD_ENCODE_URL_STR */
+-/*
+- * Given a URL encoded string, convert it to plain ascii.
+- * Since decoding always makes strings smaller, the decode is done in-place.
+- * Thus, callers should xstrdup() the argument if they do not want the
+- * argument modified.  The return is the original pointer, allowing this
+- * function to be easily used as arguments to other functions.
+- *
+- * string    The first string to decode.
+- * option_d  1 if called for httpd -d
+- *
+- * Returns a pointer to the decoded string (same as input).
+- */
+-static unsigned hex_to_bin(unsigned char c)
+-{
+-      unsigned v;
+-
+-      v = c - '0';
+-      if (v <= 9)
+-              return v;
+-      /* c | 0x20: letters to lower case, non-letters
+-       * to (potentially different) non-letters */
+-      v = (unsigned)(c | 0x20) - 'a';
+-      if (v <= 5)
+-              return v + 10;
+-      return ~0;
+-}
+-/* For testing:
+-void t(char c) { printf("'%c'(%u) %u\n", c, c, hex_to_bin(c)); }
+-int main() { t(0x10); t(0x20); t('0'); t('9'); t('A'); t('F'); t('a'); t('f');
+-t('0'-1); t('9'+1); t('A'-1); t('F'+1); t('a'-1); t('f'+1); return 0; }
+-*/
+-static char *decodeString(char *orig, int option_d)
+-{
+-      /* note that decoded string is always shorter than original */
+-      char *string = orig;
+-      char *ptr = string;
+-      char c;
+-
+-      while ((c = *ptr++) != '\0') {
+-              unsigned v;
+-
+-              if (option_d && c == '+') {
+-                      *string++ = ' ';
+-                      continue;
+-              }
+-              if (c != '%') {
+-                      *string++ = c;
+-                      continue;
+-              }
+-              v = hex_to_bin(ptr[0]);
+-              if (v > 15) {
+- bad_hex:
+-                      if (!option_d)
+-                              return NULL;
+-                      *string++ = '%';
+-                      continue;
+-              }
+-              v = (v * 16) | hex_to_bin(ptr[1]);
+-              if (v > 255)
+-                      goto bad_hex;
+-              if (!option_d && (v == '/' || v == '\0')) {
+-                      /* caller takes it as indication of invalid
+-                       * (dangerous wrt exploits) chars */
+-                      return orig + 1;
+-              }
+-              *string++ = v;
+-              ptr += 2;
+-      }
+-      *string = '\0';
+-      return orig;
+-}
+-
+ #if ENABLE_FEATURE_HTTPD_BASIC_AUTH
+ /*
+  * Decode a base64 data stream as per rfc1521.
+@@ -1876,7 +1804,7 @@ static void handle_incoming_and_exit(con
+       }
+       /* Decode URL escape sequences */
+-      tptr = decodeString(urlcopy, 0);
++      tptr = percent_decode_in_place(urlcopy, /*strict:*/ 1);
+       if (tptr == NULL)
+               send_headers_and_exit(HTTP_BAD_REQUEST);
+       if (tptr == urlcopy + 1) {
+@@ -2319,7 +2247,7 @@ int httpd_main(int argc UNUSED_PARAM, ch
+                       , &verbose
+               );
+       if (opt & OPT_DECODE_URL) {
+-              fputs(decodeString(url_for_decode, 1), stdout);
++              fputs(percent_decode_in_place(url_for_decode, /*strict:*/ 0), stdout);
+               return 0;
+       }
+ #if ENABLE_FEATURE_HTTPD_ENCODE_URL_STR
+--- a/networking/wget.c
++++ b/networking/wget.c
+@@ -373,8 +373,13 @@ static void parse_url(char *src_url, str
+       sp = strrchr(h->host, '@');
+       h->user = NULL;
+       if (sp != NULL) {
+-              h->user = h->host;
++              // URL-decode "user:password" string before base64-encoding:
++              // wget http://test:my%20pass@example.com should send
++              // Authorization: Basic dGVzdDpteSBwYXNz
++              // which decodes to "test:my pass".
++              // Standard wget and curl do this too.
+               *sp = '\0';
++              h->user = percent_decode_in_place(h->host, /*strict:*/ 0);
+               h->host = sp + 1;
+       }