summaryrefslogtreecommitdiff
path: root/ext/iconv/iconv.c
diff options
context:
space:
mode:
authorStanislav Malyshev <stas@php.net>2015-05-08 00:03:54 -0700
committerStanislav Malyshev <stas@php.net>2015-05-08 12:55:39 -0700
commitf8f1d275cfb90744e7387db72ab1857c63c352d8 (patch)
treed89a74338df15cf291e3717ef1a9100bb087387b /ext/iconv/iconv.c
parent0c92538e6f666fda25c3f72445f45923d0f8a4f6 (diff)
downloadphp-git-f8f1d275cfb90744e7387db72ab1857c63c352d8.tar.gz
Fix #48147 - implement manual handling of //IGNORE for broken libc
Diffstat (limited to 'ext/iconv/iconv.c')
-rw-r--r--ext/iconv/iconv.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/ext/iconv/iconv.c b/ext/iconv/iconv.c
index 35e4d943d5..8042916c0d 100644
--- a/ext/iconv/iconv.c
+++ b/ext/iconv/iconv.c
@@ -535,6 +535,24 @@ static php_iconv_err_t _php_iconv_appendc(smart_str *d, const char c, iconv_t cd
}
/* }}} */
+/* {{{ */
+#if ICONV_BROKEN_IGNORE
+static int _php_check_ignore(const char *charset)
+{
+ size_t clen = strlen(charset);
+ if (clen >= 9 && strcmp("//IGNORE", charset+clen-8) == 0) {
+ return 1;
+ }
+ if (clen >= 19 && strcmp("//IGNORE//TRANSLIT", charset+clen-18) == 0) {
+ return 1;
+ }
+ return 0;
+}
+#else
+#define _php_check_ignore(x) (0)
+#endif
+/* }}} */
+
/* {{{ php_iconv_string()
*/
PHP_ICONV_API php_iconv_err_t php_iconv_string(const char *in_p, size_t in_len, zend_string **out, const char *out_charset, const char *in_charset)
@@ -613,6 +631,7 @@ PHP_ICONV_API php_iconv_err_t php_iconv_string(const char *in_p, size_t in_len,
size_t bsz, result = 0;
php_iconv_err_t retval = PHP_ICONV_ERR_SUCCESS;
zend_string *out_buf;
+ int ignore_ilseq = _php_check_ignore(out_charset);
*out = NULL;
@@ -636,6 +655,17 @@ PHP_ICONV_API php_iconv_err_t php_iconv_string(const char *in_p, size_t in_len,
result = iconv(cd, (char **) &in_p, &in_left, (char **) &out_p, &out_left);
out_size = bsz - out_left;
if (result == (size_t)(-1)) {
+ if (ignore_ilseq && errno == EILSEQ) {
+ if (in_left <= 1) {
+ result = 0;
+ } else {
+ errno = 0;
+ in_p++;
+ in_left--;
+ continue;
+ }
+ }
+
if (errno == E2BIG && in_left > 0) {
/* converted string is longer than out buffer */
bsz += in_len;