diff options
Diffstat (limited to 'ext/xml/xml.c')
| -rw-r--r-- | ext/xml/xml.c | 40 | 
1 files changed, 10 insertions, 30 deletions
| diff --git a/ext/xml/xml.c b/ext/xml/xml.c index 72729d6de5..54e03d5e63 100644 --- a/ext/xml/xml.c +++ b/ext/xml/xml.c @@ -32,6 +32,7 @@  #include "zend_variables.h"  #include "ext/standard/php_string.h"  #include "ext/standard/info.h" +#include "ext/standard/html.h"  #if HAVE_XML @@ -662,7 +663,7 @@ PHPAPI char *xml_utf8_encode(const char *s, int len, int *newlen, const XML_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 +682,15 @@ PHPAPI char *xml_utf8_decode(const XML_Char *s, int len, int *newlen, const XML_  		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;  	} | 
