]> granicus.if.org Git - php/commitdiff
Improve ascii check
authorAnatol Belski <ab@php.net>
Mon, 1 Apr 2019 00:16:52 +0000 (02:16 +0200)
committerAnatol Belski <ab@php.net>
Mon, 1 Apr 2019 00:16:52 +0000 (02:16 +0200)
win32/codepage.c

index 302fcb8b45d419e67e8472a52af80cc3a949b5c5..636bc37992bf9e834363b555e941a28dc9b68b10 100644 (file)
@@ -105,6 +105,7 @@ PW32CP wchar_t *php_win32_cp_conv_ascii_to_w(const char* in, size_t in_len, size
 {/*{{{*/
        wchar_t *ret, *ret_idx;
        const char *idx = in, *end;
+       char ch_err = 0;
 
        assert(in && in_len ? in[in_len] == '\0' : 1);
 
@@ -123,29 +124,33 @@ PW32CP wchar_t *php_win32_cp_conv_ascii_to_w(const char* in, size_t in_len, size
 
                /* Process unaligned chunk. */
                while (idx < aidx) {
-                       if (!__isascii(*idx) && '\0' != *idx) {
-                               ASCII_FAIL_RETURN()
-                       }
+                       ch_err |= *idx;
                        idx++;
                }
+               if (ch_err & 0x80) {
+                       ASCII_FAIL_RETURN()
+               }
 
                /* Process aligned chunk. */
+               __m128i vec_err = _mm_setzero_si128();
                while (end - idx > 15) {
                        const __m128i block = _mm_load_si128((__m128i *)idx);
-                       if (_mm_movemask_epi8(block)) {
-                               ASCII_FAIL_RETURN()
-                       }
+                       vec_err = _mm_or_si128(vec_err, block);
                        idx += 16;
                }
+               if (_mm_movemask_epi8(vec_err)) {
+                       ASCII_FAIL_RETURN()
+               }
        }
 
        /* Process the trailing part, or otherwise process string < 16 bytes. */
        while (idx < end) {
-               if (!__isascii(*idx) && '\0' != *idx) {
-                       ASCII_FAIL_RETURN()
-               }
+               ch_err |= *idx;
                idx++;
        }
+       if (ch_err & 0x80) {
+               ASCII_FAIL_RETURN()
+       }
 
        ret = malloc((in_len+1)*sizeof(wchar_t));
        if (!ret) {
@@ -156,9 +161,6 @@ PW32CP wchar_t *php_win32_cp_conv_ascii_to_w(const char* in, size_t in_len, size
        ret_idx = ret;
        idx = in;
 
-       /* 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);