]> granicus.if.org Git - php/commitdiff
Merge branch 'PHP-7.2' into PHP-7.3
authorChristoph M. Becker <cmbecker69@gmx.de>
Thu, 9 May 2019 14:55:35 +0000 (16:55 +0200)
committerChristoph M. Becker <cmbecker69@gmx.de>
Thu, 9 May 2019 14:55:35 +0000 (16:55 +0200)
* PHP-7.2:
  Fix erroneous assertions

1  2 
win32/codepage.c

index 73645bc22b7660ff7788f5ebc431fa94815d5303,86b7179c3e7868ebee0a3d83f1cae51feed6ae00..b84909c10c1b850c3fa43e34e088457c3d5766f9
@@@ -94,16 -93,14 +94,19 @@@ PW32CP wchar_t *php_win32_cp_conv_to_w(
        return php_win32_cp_to_w_int(in, in_len, out_len, cp, flags);
  }/*}}}*/
  
 +#define ASCII_FAIL_RETURN() \
 +      if (PHP_WIN32_CP_IGNORE_LEN_P != out_len) { \
 +              *out_len = 0; \
 +      } \
 +      return NULL;
  PW32CP wchar_t *php_win32_cp_conv_ascii_to_w(const char* in, size_t in_len, size_t *out_len)
  {/*{{{*/
 -      wchar_t *ret = NULL;
 +      wchar_t *ret, *ret_idx;
        const char *idx = in, *end;
+ #if PHP_DEBUG
+       size_t save_in_len = in_len;
+ #endif
+  
        assert(in && in_len ? in[in_len] == '\0' : 1);
  
        if (!in) {
                idx++;
        }
  
 -      if (idx == end) {
 -              size_t i = 0;
 -              int k = 0;
 -              wchar_t *ret_idx;
 +      ret = malloc((in_len+1)*sizeof(wchar_t));
 +      if (!ret) {
 +              SET_ERRNO_FROM_WIN32_CODE(ERROR_OUTOFMEMORY);
 +              return NULL;
 +      }
 +
 +      ret_idx = ret;
 +      idx = in;
  
 -              ret = malloc((in_len+1)*sizeof(wchar_t));
 -              if (!ret) {
 -                      SET_ERRNO_FROM_WIN32_CODE(ERROR_OUTOFMEMORY);
 -                      return NULL;
 +      /* Check and conversion could be merged. This however would
 +              be more expencive, if a non ASCII string was passed.
 +              TODO check whether the impact is acceptable. */
 +      if (in_len > 15) {
 +              const char *aidx = (const char *)ZEND_SLIDE_TO_ALIGNED16(in);
 +
 +              /* Process unaligned chunk. */
 +              while (idx < aidx) {
 +                      *ret_idx++ = (wchar_t)*idx++;
                }
  
 -              ret_idx = ret;
 -              do {
 -                      k = _snwprintf(ret_idx, in_len - i, L"%.*hs", (int)(in_len - i), in);
 +              /* Process aligned chunk. */
 +              if (end - idx > 15) {
 +                      const __m128i mask = _mm_set1_epi32(0);
 +                      while (end - idx > 15) {
 +                              const __m128i block = _mm_load_si128((__m128i *)idx);
  
 -                      if (-1 == k) {
 -                              free(ret);
 -                              SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
 -                              return NULL;
 -                      }
 +                              {
 +                                      const __m128i lo = _mm_unpacklo_epi8(block, mask);
 +                                      _mm_storeu_si128((__m128i *)ret_idx, lo);
 +                              }
  
 -                      i += k + 1;
 +                              ret_idx += 8;
 +                              {
 +                                      const __m128i hi = _mm_unpackhi_epi8(block, mask);
 +                                      _mm_storeu_si128((__m128i *)ret_idx, hi);
 +                              }
  
 -                      if (i < in_len) {
 -                              /* Advance as this seems to be a string with \0 in it. */
 -                              in += k + 1;
 -                              ret_idx += k + 1;
 +                              idx += 16;
 +                              ret_idx += 8;
                        }
 +              }
 +      }
  
 +      /* Process the trailing part, or otherwise process string < 16 bytes. */
 +      while (idx < end) {
 +              *ret_idx++ = (wchar_t)*idx++;
 +      }
  
 -              } while (i < in_len);
 -              ret[in_len] = L'\0';
 +      ret[in_len] = L'\0';
  
-       assert(ret ? wcslen(ret) == in_len : 1);
 -              assert(ret && !save_in_len ? wcslen(ret) == in_len : 1);
++      assert(ret && !save_in_len ? wcslen(ret) == in_len : 1);
  
 -              if (PHP_WIN32_CP_IGNORE_LEN_P != out_len) {
 -                      *out_len = in_len;
 -              }
 -      } else {
 -              if (PHP_WIN32_CP_IGNORE_LEN_P != out_len) {
 -                      *out_len = 0;
 -              }
 +      if (PHP_WIN32_CP_IGNORE_LEN_P != out_len) {
 +              *out_len = in_len;
        }
  
        return ret;