@@ -739,6 +739,7 @@ static php_iconv_err_t _php_iconv_strlen(size_t *pretval, const char *str, size_
739739 size_t out_left ;
740740
741741 size_t cnt ;
742+ int more ;
742743
743744 * pretval = (size_t )-1 ;
744745
@@ -758,25 +759,23 @@ static php_iconv_err_t _php_iconv_strlen(size_t *pretval, const char *str, size_
758759
759760 errno = 0 ;
760761 out_left = 0 ;
762+ more = nbytes > 0 ;
761763
762- for (in_p = str , in_left = nbytes , cnt = 0 ; in_left > 0 ; cnt += 2 ) {
763- size_t prev_in_left ;
764+ for (in_p = str , in_left = nbytes , cnt = 0 ; more ;) {
764765 out_p = buf ;
765766 out_left = sizeof (buf );
766767
767- prev_in_left = in_left ;
768+ more = in_left > 0 ;
768769
769- if (iconv (cd , (char * * )& in_p , & in_left , (char * * ) & out_p , & out_left ) == (size_t )-1 ) {
770- if (prev_in_left == in_left ) {
771- break ;
772- }
770+ iconv (cd , more ? (char * * )& in_p : NULL , more ? & in_left : NULL , (char * * ) & out_p , & out_left );
771+ if (out_left == sizeof (buf )) {
772+ break ;
773+ } else {
774+ ZEND_ASSERT ((sizeof (buf ) - out_left ) % GENERIC_SUPERSET_NBYTES == 0 );
775+ cnt += (sizeof (buf ) - out_left ) / GENERIC_SUPERSET_NBYTES ;
773776 }
774777 }
775778
776- if (out_left > 0 ) {
777- cnt -= out_left / GENERIC_SUPERSET_NBYTES ;
778- }
779-
780779#if ICONV_SUPPORTS_ERRNO
781780 switch (errno ) {
782781 case EINVAL :
@@ -825,6 +824,7 @@ static php_iconv_err_t _php_iconv_substr(smart_str *pretval,
825824
826825 size_t cnt ;
827826 size_t total_len ;
827+ int more ;
828828
829829 err = _php_iconv_strlen (& total_len , str , nbytes , enc );
830830 if (err != PHP_ICONV_ERR_SUCCESS ) {
@@ -879,18 +879,17 @@ static php_iconv_err_t _php_iconv_substr(smart_str *pretval,
879879
880880 cd2 = (iconv_t )NULL ;
881881 errno = 0 ;
882+ more = nbytes > 0 && len > 0 ;
882883
883- for (in_p = str , in_left = nbytes , cnt = 0 ; in_left > 0 && len > 0 ; ++ cnt ) {
884- size_t prev_in_left ;
884+ for (in_p = str , in_left = nbytes , cnt = 0 ; more ; ++ cnt ) {
885885 out_p = buf ;
886886 out_left = sizeof (buf );
887887
888- prev_in_left = in_left ;
888+ more = in_left > 0 && len > 0 ;
889889
890- if (iconv (cd1 , (char * * )& in_p , & in_left , (char * * ) & out_p , & out_left ) == (size_t )-1 ) {
891- if (prev_in_left == in_left ) {
892- break ;
893- }
890+ iconv (cd1 , more ? (char * * )& in_p : NULL , more ? & in_left : NULL , (char * * ) & out_p , & out_left );
891+ if (out_left == sizeof (buf )) {
892+ break ;
894893 }
895894
896895 if ((zend_long )cnt >= offset ) {
@@ -978,6 +977,8 @@ static php_iconv_err_t _php_iconv_strpos(size_t *pretval,
978977 size_t ndl_buf_left ;
979978
980979 size_t match_ofs ;
980+ int more ;
981+ size_t iconv_ret ;
981982
982983 * pretval = (size_t )-1 ;
983984
@@ -1010,37 +1011,38 @@ static php_iconv_err_t _php_iconv_strpos(size_t *pretval,
10101011 ndl_buf_p = ZSTR_VAL (ndl_buf );
10111012 ndl_buf_left = ZSTR_LEN (ndl_buf );
10121013 match_ofs = (size_t )-1 ;
1014+ more = haystk_nbytes > 0 ;
10131015
1014- for (in_p = haystk , in_left = haystk_nbytes , cnt = 0 ; in_left > 0 ; ++ cnt ) {
1015- size_t prev_in_left ;
1016+ for (in_p = haystk , in_left = haystk_nbytes , cnt = 0 ; more ; ++ cnt ) {
10161017 out_p = buf ;
10171018 out_left = sizeof (buf );
10181019
1019- prev_in_left = in_left ;
1020+ more = in_left > 0 ;
10201021
1021- if (iconv (cd , (char * * )& in_p , & in_left , (char * * ) & out_p , & out_left ) == (size_t )-1 ) {
1022- if (prev_in_left == in_left ) {
1022+ iconv_ret = iconv (cd , more ? (char * * )& in_p : NULL , more ? & in_left : NULL , (char * * ) & out_p , & out_left );
1023+ if (out_left == sizeof (buf )) {
1024+ break ;
1025+ }
10231026#if ICONV_SUPPORTS_ERRNO
1024- switch (errno ) {
1025- case EINVAL :
1026- err = PHP_ICONV_ERR_ILLEGAL_CHAR ;
1027- break ;
1027+ if (iconv_ret == (size_t )-1 ) {
1028+ switch (errno ) {
1029+ case EINVAL :
1030+ err = PHP_ICONV_ERR_ILLEGAL_CHAR ;
1031+ break ;
10281032
1029- case EILSEQ :
1030- err = PHP_ICONV_ERR_ILLEGAL_SEQ ;
1031- break ;
1033+ case EILSEQ :
1034+ err = PHP_ICONV_ERR_ILLEGAL_SEQ ;
1035+ break ;
10321036
1033- case E2BIG :
1034- break ;
1037+ case E2BIG :
1038+ break ;
10351039
1036- default :
1037- err = PHP_ICONV_ERR_UNKNOWN ;
1038- break ;
1039- }
1040- #endif
1041- break ;
1040+ default :
1041+ err = PHP_ICONV_ERR_UNKNOWN ;
1042+ break ;
10421043 }
10431044 }
1045+ #endif
10441046 if (offset >= 0 ) {
10451047 if (cnt >= (size_t )offset ) {
10461048 if (_php_iconv_memequal (buf , ndl_buf_p , sizeof (buf ))) {
@@ -2012,6 +2014,13 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
20122014 * next_pos = p1 ;
20132015 }
20142016
2017+ if (cd != (iconv_t )(-1 )) {
2018+ _php_iconv_appendl (pretval , NULL , 0 , cd );
2019+ }
2020+ if (cd_pl != (iconv_t )(-1 )) {
2021+ _php_iconv_appendl (pretval , NULL , 0 , cd_pl );
2022+ }
2023+
20152024 smart_str_0 (pretval );
20162025out :
20172026 if (cd != (iconv_t )(-1 )) {
0 commit comments