diff options
Diffstat (limited to 'lang/php53/patches/patch-ao')
-rw-r--r-- | lang/php53/patches/patch-ao | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/lang/php53/patches/patch-ao b/lang/php53/patches/patch-ao new file mode 100644 index 00000000000..fe17b49820d --- /dev/null +++ b/lang/php53/patches/patch-ao @@ -0,0 +1,166 @@ +$NetBSD: patch-ao,v 1.1 2010/11/25 03:43:50 taca Exp $ + +Fix for CVE-2010-3870 (a part of http://secunia.com/advisories/41724/): + + http://svn.php.net/viewvc?view=revision&revision=304959 + +--- ext/xml/xml.c.orig 2010-01-05 13:03:40.000000000 +0000 ++++ ext/xml/xml.c +@@ -659,10 +659,111 @@ PHPAPI char *xml_utf8_encode(const char + } + /* }}} */ + ++/* copied from trunk's implementation of get_next_char in ext/standard/html.c */ ++#define MB_FAILURE(pos, advance) do { \ ++ *cursor = pos + (advance); \ ++ *status = FAILURE; \ ++ return 0; \ ++} while (0) ++ ++#define CHECK_LEN(pos, chars_need) ((str_len - (pos)) >= (chars_need)) ++#define utf8_lead(c) ((c) < 0x80 || ((c) >= 0xC2 && (c) <= 0xF4)) ++#define utf8_trail(c) ((c) >= 0x80 && (c) <= 0xBF) ++ ++/* {{{ php_next_utf8_char ++ */ ++static inline unsigned int php_next_utf8_char( ++ const unsigned char *str, ++ size_t str_len, ++ size_t *cursor, ++ int *status) ++{ ++ size_t pos = *cursor; ++ unsigned int this_char = 0; ++ unsigned char c; ++ ++ *status = SUCCESS; ++ ++ if (!CHECK_LEN(pos, 1)) ++ MB_FAILURE(pos, 1); ++ ++ /* We'll follow strategy 2. from section 3.6.1 of UTR #36: ++ * "In a reported illegal byte sequence, do not include any ++ * non-initial byte that encodes a valid character or is a leading ++ * byte for a valid sequence.» */ ++ c = str[pos]; ++ if (c < 0x80) { ++ this_char = c; ++ pos++; ++ } else if (c < 0xc2) { ++ MB_FAILURE(pos, 1); ++ } else if (c < 0xe0) { ++ if (!CHECK_LEN(pos, 2)) ++ MB_FAILURE(pos, 1); ++ ++ if (!utf8_trail(str[pos + 1])) { ++ MB_FAILURE(pos, utf8_lead(str[pos + 1]) ? 1 : 2); ++ } ++ this_char = ((c & 0x1f) << 6) | (str[pos + 1] & 0x3f); ++ if (this_char < 0x80) { /* non-shortest form */ ++ MB_FAILURE(pos, 2); ++ } ++ pos += 2; ++ } else if (c < 0xf0) { ++ size_t avail = str_len - pos; ++ ++ if (avail < 3 || ++ !utf8_trail(str[pos + 1]) || !utf8_trail(str[pos + 2])) { ++ if (avail < 2 || utf8_lead(str[pos + 1])) ++ MB_FAILURE(pos, 1); ++ else if (avail < 3 || utf8_lead(str[pos + 2])) ++ MB_FAILURE(pos, 2); ++ else ++ MB_FAILURE(pos, 3); ++ } ++ ++ this_char = ((c & 0x0f) << 12) | ((str[pos + 1] & 0x3f) << 6) | (str[pos + 2] & 0x3f); ++ if (this_char < 0x800) { /* non-shortest form */ ++ MB_FAILURE(pos, 3); ++ } else if (this_char >= 0xd800 && this_char <= 0xdfff) { /* surrogate */ ++ MB_FAILURE(pos, 3); ++ } ++ pos += 3; ++ } else if (c < 0xf5) { ++ size_t avail = str_len - pos; ++ ++ if (avail < 4 || ++ !utf8_trail(str[pos + 1]) || !utf8_trail(str[pos + 2]) || ++ !utf8_trail(str[pos + 3])) { ++ if (avail < 2 || utf8_lead(str[pos + 1])) ++ MB_FAILURE(pos, 1); ++ else if (avail < 3 || utf8_lead(str[pos + 2])) ++ MB_FAILURE(pos, 2); ++ else if (avail < 4 || utf8_lead(str[pos + 3])) ++ MB_FAILURE(pos, 3); ++ else ++ MB_FAILURE(pos, 4); ++ } ++ ++ this_char = ((c & 0x07) << 18) | ((str[pos + 1] & 0x3f) << 12) | ((str[pos + 2] & 0x3f) << 6) | (str[pos + 3] & 0x3f); ++ if (this_char < 0x10000 || this_char > 0x10FFFF) { /* non-shortest form or outside range */ ++ MB_FAILURE(pos, 4); ++ } ++ pos += 4; ++ } else { ++ MB_FAILURE(pos, 1); ++ } ++ ++ *cursor = pos; ++ return this_char; ++} ++/* }}} */ ++ ++ + /* {{{ xml_utf8_decode */ + PHPAPI char *xml_utf8_decode(const XML_Char *s, int len, int *newlen, const XML_Char *encoding) + { +- int pos = len; ++ size_t pos = 0; + char *newbuf = emalloc(len + 1); + unsigned int c; + char (*decoder)(unsigned short) = NULL; +@@ -681,36 +782,15 @@ PHPAPI char *xml_utf8_decode(const XML_C + newbuf[*newlen] = '\0'; + return newbuf; + } +- while (pos > 0) { +- c = (unsigned char)(*s); +- if (c >= 0xf0) { /* four bytes encoded, 21 bits */ +- if(pos-4 >= 0) { +- c = ((s[0]&7)<<18) | ((s[1]&63)<<12) | ((s[2]&63)<<6) | (s[3]&63); +- } else { +- c = '?'; +- } +- s += 4; +- pos -= 4; +- } else if (c >= 0xe0) { /* three bytes encoded, 16 bits */ +- if(pos-3 >= 0) { +- c = ((s[0]&63)<<12) | ((s[1]&63)<<6) | (s[2]&63); +- } else { +- c = '?'; +- } +- s += 3; +- pos -= 3; +- } else if (c >= 0xc0) { /* two bytes encoded, 11 bits */ +- if(pos-2 >= 0) { +- c = ((s[0]&63)<<6) | (s[1]&63); +- } else { +- c = '?'; +- } +- s += 2; +- pos -= 2; +- } else { +- s++; +- pos--; ++ ++ while (pos < (size_t)len) { ++ int status = FAILURE; ++ c = php_next_utf8_char((const unsigned char*)s, (size_t) len, &pos, &status); ++ ++ if (status == FAILURE || c > 0xFFU) { ++ c = '?'; + } ++ + newbuf[*newlen] = decoder ? decoder(c) : c; + ++*newlen; + } |