diff options
author | Dmitry Stogov <dmitry@zend.com> | 2017-11-16 17:10:04 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2017-11-16 17:10:04 +0300 |
commit | 73bde7bbd0e2207383752581d10bdd92b897dd37 (patch) | |
tree | 5cc6fee8f4b403f8c14186ebca6fe5ca9ac59fc8 | |
parent | ccc12b82da5dd10b44ab067b68b762298a9eb4eb (diff) | |
parent | a370a6af647e27a334676a2c87bf686c6c973423 (diff) | |
download | php-git-73bde7bbd0e2207383752581d10bdd92b897dd37.tar.gz |
Merge branch 'master' of git.php.net:php-src
* 'master' of git.php.net:php-src:
Fix (*NO_JIT) usage when JIT is enabled
Refactor ASCII to wide conversion
-rw-r--r-- | ext/pcre/php_pcre.c | 5 | ||||
-rw-r--r-- | ext/pcre/tests/no_jit_bug70110.phpt | 16 | ||||
-rw-r--r-- | win32/codepage.c | 91 |
3 files changed, 68 insertions, 44 deletions
diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c index 82c0323f1c..f53f39352a 100644 --- a/ext/pcre/php_pcre.c +++ b/ext/pcre/php_pcre.c @@ -726,7 +726,10 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex) /* Enable PCRE JIT compiler */ rc = pcre2_jit_compile(re, PCRE2_JIT_COMPLETE); if (EXPECTED(rc >= 0)) { - poptions |= PREG_JIT; + size_t jit_size = 0; + if (!pcre2_pattern_info(re, PCRE2_INFO_JITSIZE, &jit_size) && jit_size > 0) { + poptions |= PREG_JIT; + } } else { pcre2_get_error_message(rc, error, sizeof(error)); php_error_docref(NULL, E_WARNING, "JIT compilation failed: %s", error); diff --git a/ext/pcre/tests/no_jit_bug70110.phpt b/ext/pcre/tests/no_jit_bug70110.phpt new file mode 100644 index 0000000000..d1ce7abc4e --- /dev/null +++ b/ext/pcre/tests/no_jit_bug70110.phpt @@ -0,0 +1,16 @@ +--TEST-- +Test (*NO_JIT) doesn't crash when JIT enabled +--SKIPIF-- +<?php if (!PCRE_JIT_SUPPORT) die("skip pcre jit support required"); ?> +--FILE-- +<?php + +var_dump(preg_match('/(*NO_JIT)^(A{1,2}B)+$$/',str_repeat('AB',8192))); +var_dump(preg_match('~(*NO_JIT)(a)*~', str_repeat('a', 5431), $match)) + +?> +==DONE== +--EXPECTF-- +int(1) +int(1) +==DONE== diff --git a/win32/codepage.c b/win32/codepage.c index ab6d0a1e5f..d30051aad5 100644 --- a/win32/codepage.c +++ b/win32/codepage.c @@ -20,6 +20,7 @@ #include "php.h" #include "SAPI.h" +#include <emmintrin.h> ZEND_TLS const struct php_win32_cp *cur_cp = NULL; ZEND_TLS const struct php_win32_cp *orig_cp = NULL; @@ -93,11 +94,19 @@ PW32CP wchar_t *php_win32_cp_conv_to_w(DWORD cp, DWORD flags, const char* in, si 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; const char *idx = in, *end; - BOOL failed = FALSE; + size_t i = 0; + int k = 0; + wchar_t *ret_idx; + assert(in && in_len ? in[in_len] == '\0' : 1); @@ -115,6 +124,15 @@ PW32CP wchar_t *php_win32_cp_conv_ascii_to_w(const char* in, size_t in_len, size end = in + in_len; + /* The ASCII check part can be moved into a separate function. */ + while (end - idx > 16) { + __m128i block = _mm_loadu_si128((__m128i *)idx); + if (_mm_movemask_epi8(block)) { + ASCII_FAIL_RETURN() + } + idx += 16; + } + while (end - idx > 8) { char ch0 = *idx; char ch1 = *(idx + 1); @@ -127,70 +145,57 @@ PW32CP wchar_t *php_win32_cp_conv_ascii_to_w(const char* in, size_t in_len, size if (!__isascii(ch0) || !__isascii(ch1) || !__isascii(ch2) || !__isascii(ch3) || !__isascii(ch4) || !__isascii(ch5) || !__isascii(ch6) || !__isascii(ch7)) { - failed = TRUE; - break; + ASCII_FAIL_RETURN() } idx += 8; } /* Finish the job on remaining chars. */ - if (!failed) { - while (idx != end) { - if (!__isascii(*idx) && '\0' != *idx) { - failed = TRUE; - break; - } - idx++; + while (idx != end) { + if (!__isascii(*idx) && '\0' != *idx) { + ASCII_FAIL_RETURN() } + idx++; } - if (!failed) { - 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 = malloc((in_len+1)*sizeof(wchar_t)); - if (!ret) { - SET_ERRNO_FROM_WIN32_CODE(ERROR_OUTOFMEMORY); + ret_idx = ret; + do { + k = _snwprintf(ret_idx, in_len - i, L"%.*hs", (int)(in_len - i), in); + + if (-1 == k) { + free(ret); + SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER); return NULL; } - ret_idx = ret; - do { - k = _snwprintf(ret_idx, in_len - i, L"%.*hs", (int)(in_len - i), in); - - if (-1 == k) { - free(ret); - SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER); - return NULL; - } - - i += k + 1; + i += k + 1; - if (i < in_len) { - /* Advance as this seems to be a string with \0 in it. */ - in += k + 1; - ret_idx += k + 1; - } + if (i < in_len) { + /* Advance as this seems to be a string with \0 in it. */ + in += k + 1; + ret_idx += k + 1; + } - } while (i < in_len); - ret[in_len] = L'\0'; + } while (i < in_len); + ret[in_len] = L'\0'; - assert(ret ? wcslen(ret) == in_len : 1); + assert(ret ? 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; }/*}}}*/ +#undef ASCII_FAIL_RETURN __forceinline static char *php_win32_cp_from_w_int(const wchar_t* in, size_t in_len, size_t *out_len, UINT cp, DWORD flags) {/*{{{*/ |