diff options
author | Stanislav Malyshev <stas@php.net> | 2015-05-08 00:03:54 -0700 |
---|---|---|
committer | Stanislav Malyshev <stas@php.net> | 2015-05-08 12:55:39 -0700 |
commit | f8f1d275cfb90744e7387db72ab1857c63c352d8 (patch) | |
tree | d89a74338df15cf291e3717ef1a9100bb087387b /ext/iconv/iconv.c | |
parent | 0c92538e6f666fda25c3f72445f45923d0f8a4f6 (diff) | |
download | php-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.c | 30 |
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; |