@@ -520,6 +520,7 @@ zend_result php_json_escape_string(
520520#ifdef __SSE2__
521521 while (len >= sizeof (__m128i )) {
522522 const __m128i input = _mm_loadu_si128 ((__m128i * ) (s + pos ));
523+ /* signed compare, so checks for unsigned ASCII >= 0x80 as well */
523524 const __m128i input_range = _mm_cmplt_epi8 (input , _mm_set1_epi8 (32 ));
524525
525526 int max_shift = 16 ;
@@ -559,25 +560,26 @@ zend_result php_json_escape_string(
559560 len -= MIN (max_shift , shift );
560561 break ;
561562 }
563+
562564 int shift = zend_ulong_nlz (mask ) - 16 - (SIZEOF_ZEND_LONG == 8 ? 32 : 0 ); /* skips over everything */
565+ smart_str_appendl (buf , s , pos );
566+ s += pos ;
567+ pos = shift ;
568+
563569 do {
564570 /* Note that we shift the input forward, so we have to shift the mask as well,
565571 * beyond the to-be-escaped character */
566572 int len = zend_ulong_ntz (mask );
567573 mask >>= len + 1 ;
568574
569- smart_str_appendl (buf , s , len + pos );
575+ smart_str_appendl (buf , s , len );
570576
571- pos += len ;
572- us = (unsigned char )s [pos ];
573- s += pos + 1 ; /* skip 'us' too */
574- pos = 0 ;
577+ us = (unsigned char )s [len ];
578+ s += len + 1 ; /* skip 'us' too */
575579
576580 bool handled = php_json_printable_ascii_escape (buf , us , options );
577581 ZEND_ASSERT (handled == true);
578582 } while (mask != 0 );
579-
580- pos += shift ;
581583 } else {
582584 if (max_shift < 16 ) {
583585 pos += max_shift ;
0 commit comments