@@ -724,6 +724,7 @@ static php_iconv_err_t _php_iconv_strlen(size_t *pretval, const char *str, size_
724724 size_t out_left ;
725725
726726 size_t cnt ;
727+ int more ;
727728
728729 * pretval = (size_t )-1 ;
729730
@@ -743,25 +744,23 @@ static php_iconv_err_t _php_iconv_strlen(size_t *pretval, const char *str, size_
743744
744745 errno = 0 ;
745746 out_left = 0 ;
747+ more = nbytes > 0 ;
746748
747- for (in_p = str , in_left = nbytes , cnt = 0 ; in_left > 0 ; cnt += 2 ) {
748- size_t prev_in_left ;
749+ for (in_p = str , in_left = nbytes , cnt = 0 ; more ;) {
749750 out_p = buf ;
750751 out_left = sizeof (buf );
751752
752- prev_in_left = in_left ;
753+ more = in_left > 0 ;
753754
754- if (iconv (cd , (char * * )& in_p , & in_left , (char * * ) & out_p , & out_left ) == (size_t )-1 ) {
755- if (prev_in_left == in_left ) {
756- break ;
757- }
755+ iconv (cd , more ? (char * * )& in_p : NULL , more ? & in_left : NULL , (char * * ) & out_p , & out_left );
756+ if (out_left == sizeof (buf )) {
757+ break ;
758+ } else {
759+ ZEND_ASSERT ((sizeof (buf ) - out_left ) % GENERIC_SUPERSET_NBYTES == 0 );
760+ cnt += (sizeof (buf ) - out_left ) / GENERIC_SUPERSET_NBYTES ;
758761 }
759762 }
760763
761- if (out_left > 0 ) {
762- cnt -= out_left / GENERIC_SUPERSET_NBYTES ;
763- }
764-
765764#if ICONV_SUPPORTS_ERRNO
766765 switch (errno ) {
767766 case EINVAL :
@@ -810,6 +809,7 @@ static php_iconv_err_t _php_iconv_substr(smart_str *pretval,
810809
811810 size_t cnt ;
812811 size_t total_len ;
812+ int more ;
813813
814814 err = _php_iconv_strlen (& total_len , str , nbytes , enc );
815815 if (err != PHP_ICONV_ERR_SUCCESS ) {
@@ -864,18 +864,17 @@ static php_iconv_err_t _php_iconv_substr(smart_str *pretval,
864864
865865 cd2 = (iconv_t )NULL ;
866866 errno = 0 ;
867+ more = nbytes > 0 && len > 0 ;
867868
868- for (in_p = str , in_left = nbytes , cnt = 0 ; in_left > 0 && len > 0 ; ++ cnt ) {
869- size_t prev_in_left ;
869+ for (in_p = str , in_left = nbytes , cnt = 0 ; more ; ++ cnt ) {
870870 out_p = buf ;
871871 out_left = sizeof (buf );
872872
873- prev_in_left = in_left ;
873+ more = in_left > 0 && len > 0 ;
874874
875- if (iconv (cd1 , (char * * )& in_p , & in_left , (char * * ) & out_p , & out_left ) == (size_t )-1 ) {
876- if (prev_in_left == in_left ) {
877- break ;
878- }
875+ iconv (cd1 , more ? (char * * )& in_p : NULL , more ? & in_left : NULL , (char * * ) & out_p , & out_left );
876+ if (out_left == sizeof (buf )) {
877+ break ;
879878 }
880879
881880 if ((zend_long )cnt >= offset ) {
@@ -963,6 +962,8 @@ static php_iconv_err_t _php_iconv_strpos(size_t *pretval,
963962 size_t ndl_buf_left ;
964963
965964 size_t match_ofs ;
965+ int more ;
966+ size_t iconv_ret ;
966967
967968 * pretval = (size_t )-1 ;
968969
@@ -995,37 +996,38 @@ static php_iconv_err_t _php_iconv_strpos(size_t *pretval,
995996 ndl_buf_p = ZSTR_VAL (ndl_buf );
996997 ndl_buf_left = ZSTR_LEN (ndl_buf );
997998 match_ofs = (size_t )-1 ;
999+ more = haystk_nbytes > 0 ;
9981000
999- for (in_p = haystk , in_left = haystk_nbytes , cnt = 0 ; in_left > 0 ; ++ cnt ) {
1000- size_t prev_in_left ;
1001+ for (in_p = haystk , in_left = haystk_nbytes , cnt = 0 ; more ; ++ cnt ) {
10011002 out_p = buf ;
10021003 out_left = sizeof (buf );
10031004
1004- prev_in_left = in_left ;
1005+ more = in_left > 0 ;
10051006
1006- if (iconv (cd , (char * * )& in_p , & in_left , (char * * ) & out_p , & out_left ) == (size_t )-1 ) {
1007- if (prev_in_left == in_left ) {
1007+ iconv_ret = iconv (cd , more ? (char * * )& in_p : NULL , more ? & in_left : NULL , (char * * ) & out_p , & out_left );
1008+ if (out_left == sizeof (buf )) {
1009+ break ;
1010+ }
10081011#if ICONV_SUPPORTS_ERRNO
1009- switch (errno ) {
1010- case EINVAL :
1011- err = PHP_ICONV_ERR_ILLEGAL_CHAR ;
1012- break ;
1012+ if (iconv_ret == (size_t )-1 ) {
1013+ switch (errno ) {
1014+ case EINVAL :
1015+ err = PHP_ICONV_ERR_ILLEGAL_CHAR ;
1016+ break ;
10131017
1014- case EILSEQ :
1015- err = PHP_ICONV_ERR_ILLEGAL_SEQ ;
1016- break ;
1018+ case EILSEQ :
1019+ err = PHP_ICONV_ERR_ILLEGAL_SEQ ;
1020+ break ;
10171021
1018- case E2BIG :
1019- break ;
1022+ case E2BIG :
1023+ break ;
10201024
1021- default :
1022- err = PHP_ICONV_ERR_UNKNOWN ;
1023- break ;
1024- }
1025- #endif
1026- break ;
1025+ default :
1026+ err = PHP_ICONV_ERR_UNKNOWN ;
1027+ break ;
10271028 }
10281029 }
1030+ #endif
10291031 if (offset >= 0 ) {
10301032 if (cnt >= (size_t )offset ) {
10311033 if (_php_iconv_memequal (buf , ndl_buf_p , sizeof (buf ))) {
@@ -1997,6 +1999,13 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
19971999 * next_pos = p1 ;
19982000 }
19992001
2002+ if (cd != (iconv_t )(-1 )) {
2003+ _php_iconv_appendl (pretval , NULL , 0 , cd );
2004+ }
2005+ if (cd_pl != (iconv_t )(-1 )) {
2006+ _php_iconv_appendl (pretval , NULL , 0 , cd_pl );
2007+ }
2008+
20002009 smart_str_0 (pretval );
20012010out :
20022011 if (cd != (iconv_t )(-1 )) {
0 commit comments