@@ -578,6 +578,7 @@ static php_iconv_err_t _php_iconv_strlen(size_t *pretval, const char *str, size_
578578 size_t out_left ;
579579
580580 size_t cnt ;
581+ int more ;
581582
582583 * pretval = (size_t )-1 ;
583584
@@ -593,25 +594,23 @@ static php_iconv_err_t _php_iconv_strlen(size_t *pretval, const char *str, size_
593594
594595 errno = 0 ;
595596 out_left = 0 ;
597+ more = nbytes > 0 ;
596598
597- for (in_p = str , in_left = nbytes , cnt = 0 ; in_left > 0 ; cnt += 2 ) {
598- size_t prev_in_left ;
599+ for (in_p = str , in_left = nbytes , cnt = 0 ; more ;) {
599600 out_p = buf ;
600601 out_left = sizeof (buf );
601602
602- prev_in_left = in_left ;
603+ more = in_left > 0 ;
603604
604- if (iconv (cd , (char * * )& in_p , & in_left , (char * * ) & out_p , & out_left ) == (size_t )-1 ) {
605- if (prev_in_left == in_left ) {
606- break ;
607- }
605+ iconv (cd , more ? (char * * )& in_p : NULL , more ? & in_left : NULL , (char * * ) & out_p , & out_left );
606+ if (out_left == sizeof (buf )) {
607+ break ;
608+ } else {
609+ ZEND_ASSERT ((sizeof (buf ) - out_left ) % GENERIC_SUPERSET_NBYTES == 0 );
610+ cnt += (sizeof (buf ) - out_left ) / GENERIC_SUPERSET_NBYTES ;
608611 }
609612 }
610613
611- if (out_left > 0 ) {
612- cnt -= out_left / GENERIC_SUPERSET_NBYTES ;
613- }
614-
615614 switch (errno ) {
616615 case EINVAL :
617616 err = PHP_ICONV_ERR_ILLEGAL_CHAR ;
@@ -656,6 +655,7 @@ static php_iconv_err_t _php_iconv_substr(smart_str *pretval,
656655
657656 size_t cnt ;
658657 size_t total_len ;
658+ int more ;
659659
660660 err = _php_iconv_strlen (& total_len , str , nbytes , enc );
661661 if (err != PHP_ICONV_ERR_SUCCESS ) {
@@ -706,18 +706,17 @@ static php_iconv_err_t _php_iconv_substr(smart_str *pretval,
706706
707707 cd2 = (iconv_t )NULL ;
708708 errno = 0 ;
709+ more = nbytes > 0 && len > 0 ;
709710
710- for (in_p = str , in_left = nbytes , cnt = 0 ; in_left > 0 && len > 0 ; ++ cnt ) {
711- size_t prev_in_left ;
711+ for (in_p = str , in_left = nbytes , cnt = 0 ; more ; ++ cnt ) {
712712 out_p = buf ;
713713 out_left = sizeof (buf );
714714
715- prev_in_left = in_left ;
715+ more = in_left > 0 && len > 0 ;
716716
717- if (iconv (cd1 , (char * * )& in_p , & in_left , (char * * ) & out_p , & out_left ) == (size_t )-1 ) {
718- if (prev_in_left == in_left ) {
719- break ;
720- }
717+ iconv (cd1 , more ? (char * * )& in_p : NULL , more ? & in_left : NULL , (char * * ) & out_p , & out_left );
718+ if (out_left == sizeof (buf )) {
719+ break ;
721720 }
722721
723722 if ((zend_long )cnt >= offset ) {
@@ -799,6 +798,8 @@ static php_iconv_err_t _php_iconv_strpos(size_t *pretval,
799798 size_t ndl_buf_left ;
800799
801800 size_t match_ofs ;
801+ int more ;
802+ size_t iconv_ret ;
802803
803804 * pretval = (size_t )-1 ;
804805
@@ -827,33 +828,34 @@ static php_iconv_err_t _php_iconv_strpos(size_t *pretval,
827828 ndl_buf_p = ZSTR_VAL (ndl_buf );
828829 ndl_buf_left = ZSTR_LEN (ndl_buf );
829830 match_ofs = (size_t )-1 ;
831+ more = haystk_nbytes > 0 ;
830832
831- for (in_p = haystk , in_left = haystk_nbytes , cnt = 0 ; in_left > 0 ; ++ cnt ) {
832- size_t prev_in_left ;
833+ for (in_p = haystk , in_left = haystk_nbytes , cnt = 0 ; more ; ++ cnt ) {
833834 out_p = buf ;
834835 out_left = sizeof (buf );
835836
836- prev_in_left = in_left ;
837+ more = in_left > 0 ;
837838
838- if (iconv (cd , (char * * )& in_p , & in_left , (char * * ) & out_p , & out_left ) == (size_t )-1 ) {
839- if (prev_in_left == in_left ) {
840- switch (errno ) {
841- case EINVAL :
842- err = PHP_ICONV_ERR_ILLEGAL_CHAR ;
843- break ;
839+ iconv_ret = iconv (cd , more ? (char * * )& in_p : NULL , more ? & in_left : NULL , (char * * ) & out_p , & out_left );
840+ if (out_left == sizeof (buf )) {
841+ break ;
842+ }
843+ if (iconv_ret == (size_t )-1 ) {
844+ switch (errno ) {
845+ case EINVAL :
846+ err = PHP_ICONV_ERR_ILLEGAL_CHAR ;
847+ break ;
844848
845- case EILSEQ :
846- err = PHP_ICONV_ERR_ILLEGAL_SEQ ;
847- break ;
849+ case EILSEQ :
850+ err = PHP_ICONV_ERR_ILLEGAL_SEQ ;
851+ break ;
848852
849- case E2BIG :
850- break ;
853+ case E2BIG :
854+ break ;
851855
852- default :
853- err = PHP_ICONV_ERR_UNKNOWN ;
854- break ;
855- }
856- break ;
856+ default :
857+ err = PHP_ICONV_ERR_UNKNOWN ;
858+ break ;
857859 }
858860 }
859861 if (offset >= 0 ) {
@@ -1777,6 +1779,13 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
17771779 * next_pos = p1 ;
17781780 }
17791781
1782+ if (cd != (iconv_t )(-1 )) {
1783+ _php_iconv_appendl (pretval , NULL , 0 , cd );
1784+ }
1785+ if (cd_pl != (iconv_t )(-1 )) {
1786+ _php_iconv_appendl (pretval , NULL , 0 , cd_pl );
1787+ }
1788+
17801789 smart_str_0 (pretval );
17811790out :
17821791 if (cd != (iconv_t )(-1 )) {
0 commit comments