mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00

Excerpt from the release news: Version 10.37 26-May-2021 ------------------------- A few more bug fixes and tidies. The only change of real note is the removal of the actual POSIX names regcomp etc. from the POSIX wrapper library because these have caused issues for some applications (see 10.33 #2 below). Version 10.36 04-December-2020 ------------------------------ Again, mainly bug fixes and tidies. The only enhancements are the addition of GNU grep's -m (aka --max-count) option to pcre2grep, and also unifying the handling of substitution strings for both -O and callouts in pcre2grep, with the addition of $x{...} and $o{...} to allow for characters whose code points are greater than 255 in Unicode mode. NOTE: there is an outstanding issue with JIT support for MacOS on arm64 hardware. For details, please see Bugzilla issue #2618. Signed-off-by: Anatol Belski <ab@php.net>
347 lines
8.2 KiB
C
347 lines
8.2 KiB
C
/*************************************************
|
|
* Perl-Compatible Regular Expressions *
|
|
*************************************************/
|
|
|
|
/* PCRE is a library of functions to support regular expressions whose syntax
|
|
and semantics are as close as possible to those of the Perl 5 language.
|
|
|
|
Written by Philip Hazel
|
|
This module by Zoltan Herczeg and Sebastian Pop
|
|
Original API code Copyright (c) 1997-2012 University of Cambridge
|
|
New API code Copyright (c) 2016-2019 University of Cambridge
|
|
|
|
-----------------------------------------------------------------------------
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions are met:
|
|
|
|
* Redistributions of source code must retain the above copyright notice,
|
|
this list of conditions and the following disclaimer.
|
|
|
|
* Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
|
|
* Neither the name of the University of Cambridge nor the names of its
|
|
contributors may be used to endorse or promote products derived from
|
|
this software without specific prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
POSSIBILITY OF SUCH DAMAGE.
|
|
-----------------------------------------------------------------------------
|
|
*/
|
|
|
|
# if defined(FFCS)
|
|
# if defined(FF_UTF)
|
|
# define FF_FUN ffcs_utf
|
|
# else
|
|
# define FF_FUN ffcs
|
|
# endif
|
|
|
|
# elif defined(FFCS_2)
|
|
# if defined(FF_UTF)
|
|
# define FF_FUN ffcs_2_utf
|
|
# else
|
|
# define FF_FUN ffcs_2
|
|
# endif
|
|
|
|
# elif defined(FFCS_MASK)
|
|
# if defined(FF_UTF)
|
|
# define FF_FUN ffcs_mask_utf
|
|
# else
|
|
# define FF_FUN ffcs_mask
|
|
# endif
|
|
|
|
# elif defined(FFCPS_0)
|
|
# if defined (FF_UTF)
|
|
# define FF_FUN ffcps_0_utf
|
|
# else
|
|
# define FF_FUN ffcps_0
|
|
# endif
|
|
|
|
# elif defined (FFCPS_1)
|
|
# if defined (FF_UTF)
|
|
# define FF_FUN ffcps_1_utf
|
|
# else
|
|
# define FF_FUN ffcps_1
|
|
# endif
|
|
|
|
# elif defined (FFCPS_DEFAULT)
|
|
# if defined (FF_UTF)
|
|
# define FF_FUN ffcps_default_utf
|
|
# else
|
|
# define FF_FUN ffcps_default
|
|
# endif
|
|
# endif
|
|
|
|
static sljit_u8* SLJIT_FUNC FF_FUN(sljit_u8 *str_end, sljit_u8 *str_ptr, sljit_uw offs1, sljit_uw offs2, sljit_uw chars)
|
|
#undef FF_FUN
|
|
{
|
|
quad_word qw;
|
|
int_char ic;
|
|
|
|
SLJIT_UNUSED_ARG(offs1);
|
|
SLJIT_UNUSED_ARG(offs2);
|
|
|
|
ic.x = chars;
|
|
|
|
#if defined(FFCS)
|
|
sljit_u8 c1 = ic.c.c1;
|
|
vect_t vc1 = VDUPQ(c1);
|
|
|
|
#elif defined(FFCS_2)
|
|
sljit_u8 c1 = ic.c.c1;
|
|
vect_t vc1 = VDUPQ(c1);
|
|
sljit_u8 c2 = ic.c.c2;
|
|
vect_t vc2 = VDUPQ(c2);
|
|
|
|
#elif defined(FFCS_MASK)
|
|
sljit_u8 c1 = ic.c.c1;
|
|
vect_t vc1 = VDUPQ(c1);
|
|
sljit_u8 mask = ic.c.c2;
|
|
vect_t vmask = VDUPQ(mask);
|
|
#endif
|
|
|
|
#if defined(FFCPS)
|
|
compare_type compare1_type = compare_match1;
|
|
compare_type compare2_type = compare_match1;
|
|
vect_t cmp1a, cmp1b, cmp2a, cmp2b;
|
|
const sljit_u32 diff = IN_UCHARS(offs1 - offs2);
|
|
PCRE2_UCHAR char1a = ic.c.c1;
|
|
PCRE2_UCHAR char2a = ic.c.c3;
|
|
|
|
# ifdef FFCPS_CHAR1A2A
|
|
cmp1a = VDUPQ(char1a);
|
|
cmp2a = VDUPQ(char2a);
|
|
cmp1b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
|
|
cmp2b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
|
|
# else
|
|
PCRE2_UCHAR char1b = ic.c.c2;
|
|
PCRE2_UCHAR char2b = ic.c.c4;
|
|
if (char1a == char1b)
|
|
{
|
|
cmp1a = VDUPQ(char1a);
|
|
cmp1b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
|
|
}
|
|
else
|
|
{
|
|
sljit_u32 bit1 = char1a ^ char1b;
|
|
if (is_powerof2(bit1))
|
|
{
|
|
compare1_type = compare_match1i;
|
|
cmp1a = VDUPQ(char1a | bit1);
|
|
cmp1b = VDUPQ(bit1);
|
|
}
|
|
else
|
|
{
|
|
compare1_type = compare_match2;
|
|
cmp1a = VDUPQ(char1a);
|
|
cmp1b = VDUPQ(char1b);
|
|
}
|
|
}
|
|
|
|
if (char2a == char2b)
|
|
{
|
|
cmp2a = VDUPQ(char2a);
|
|
cmp2b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
|
|
}
|
|
else
|
|
{
|
|
sljit_u32 bit2 = char2a ^ char2b;
|
|
if (is_powerof2(bit2))
|
|
{
|
|
compare2_type = compare_match1i;
|
|
cmp2a = VDUPQ(char2a | bit2);
|
|
cmp2b = VDUPQ(bit2);
|
|
}
|
|
else
|
|
{
|
|
compare2_type = compare_match2;
|
|
cmp2a = VDUPQ(char2a);
|
|
cmp2b = VDUPQ(char2b);
|
|
}
|
|
}
|
|
# endif
|
|
|
|
str_ptr += IN_UCHARS(offs1);
|
|
#endif
|
|
|
|
#if PCRE2_CODE_UNIT_WIDTH != 8
|
|
vect_t char_mask = VDUPQ(0xff);
|
|
#endif
|
|
|
|
#if defined(FF_UTF)
|
|
restart:;
|
|
#endif
|
|
|
|
#if defined(FFCPS)
|
|
sljit_u8 *p1 = str_ptr - diff;
|
|
#endif
|
|
sljit_s32 align_offset = ((uint64_t)str_ptr & 0xf);
|
|
str_ptr = (sljit_u8 *) ((uint64_t)str_ptr & ~0xf);
|
|
vect_t data = VLD1Q(str_ptr);
|
|
#if PCRE2_CODE_UNIT_WIDTH != 8
|
|
data = VANDQ(data, char_mask);
|
|
#endif
|
|
|
|
#if defined(FFCS)
|
|
vect_t eq = VCEQQ(data, vc1);
|
|
|
|
#elif defined(FFCS_2)
|
|
vect_t eq1 = VCEQQ(data, vc1);
|
|
vect_t eq2 = VCEQQ(data, vc2);
|
|
vect_t eq = VORRQ(eq1, eq2);
|
|
|
|
#elif defined(FFCS_MASK)
|
|
vect_t eq = VORRQ(data, vmask);
|
|
eq = VCEQQ(eq, vc1);
|
|
|
|
#elif defined(FFCPS)
|
|
# if defined(FFCPS_DIFF1)
|
|
vect_t prev_data = data;
|
|
# endif
|
|
|
|
vect_t data2;
|
|
if (p1 < str_ptr)
|
|
{
|
|
data2 = VLD1Q(str_ptr - diff);
|
|
#if PCRE2_CODE_UNIT_WIDTH != 8
|
|
data2 = VANDQ(data2, char_mask);
|
|
#endif
|
|
}
|
|
else
|
|
data2 = shift_left_n_lanes(data, offs1 - offs2);
|
|
|
|
if (compare1_type == compare_match1)
|
|
data = VCEQQ(data, cmp1a);
|
|
else
|
|
data = fast_forward_char_pair_compare(compare1_type, data, cmp1a, cmp1b);
|
|
|
|
if (compare2_type == compare_match1)
|
|
data2 = VCEQQ(data2, cmp2a);
|
|
else
|
|
data2 = fast_forward_char_pair_compare(compare2_type, data2, cmp2a, cmp2b);
|
|
|
|
vect_t eq = VANDQ(data, data2);
|
|
#endif
|
|
|
|
VST1Q(qw.mem, eq);
|
|
/* Ignore matches before the first STR_PTR. */
|
|
if (align_offset < 8)
|
|
{
|
|
qw.dw[0] >>= align_offset * 8;
|
|
if (qw.dw[0])
|
|
{
|
|
str_ptr += align_offset + __builtin_ctzll(qw.dw[0]) / 8;
|
|
goto match;
|
|
}
|
|
if (qw.dw[1])
|
|
{
|
|
str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8;
|
|
goto match;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
qw.dw[1] >>= (align_offset - 8) * 8;
|
|
if (qw.dw[1])
|
|
{
|
|
str_ptr += align_offset + __builtin_ctzll(qw.dw[1]) / 8;
|
|
goto match;
|
|
}
|
|
}
|
|
str_ptr += 16;
|
|
|
|
while (str_ptr < str_end)
|
|
{
|
|
vect_t orig_data = VLD1Q(str_ptr);
|
|
#if PCRE2_CODE_UNIT_WIDTH != 8
|
|
orig_data = VANDQ(orig_data, char_mask);
|
|
#endif
|
|
data = orig_data;
|
|
|
|
#if defined(FFCS)
|
|
eq = VCEQQ(data, vc1);
|
|
|
|
#elif defined(FFCS_2)
|
|
eq1 = VCEQQ(data, vc1);
|
|
eq2 = VCEQQ(data, vc2);
|
|
eq = VORRQ(eq1, eq2);
|
|
|
|
#elif defined(FFCS_MASK)
|
|
eq = VORRQ(data, vmask);
|
|
eq = VCEQQ(eq, vc1);
|
|
#endif
|
|
|
|
#if defined(FFCPS)
|
|
# if defined (FFCPS_DIFF1)
|
|
data2 = VEXTQ(prev_data, data, VECTOR_FACTOR - 1);
|
|
# else
|
|
data2 = VLD1Q(str_ptr - diff);
|
|
# if PCRE2_CODE_UNIT_WIDTH != 8
|
|
data2 = VANDQ(data2, char_mask);
|
|
# endif
|
|
# endif
|
|
|
|
# ifdef FFCPS_CHAR1A2A
|
|
data = VCEQQ(data, cmp1a);
|
|
data2 = VCEQQ(data2, cmp2a);
|
|
# else
|
|
if (compare1_type == compare_match1)
|
|
data = VCEQQ(data, cmp1a);
|
|
else
|
|
data = fast_forward_char_pair_compare(compare1_type, data, cmp1a, cmp1b);
|
|
if (compare2_type == compare_match1)
|
|
data2 = VCEQQ(data2, cmp2a);
|
|
else
|
|
data2 = fast_forward_char_pair_compare(compare2_type, data2, cmp2a, cmp2b);
|
|
# endif
|
|
|
|
eq = VANDQ(data, data2);
|
|
#endif
|
|
|
|
VST1Q(qw.mem, eq);
|
|
if (qw.dw[0])
|
|
str_ptr += __builtin_ctzll(qw.dw[0]) / 8;
|
|
else if (qw.dw[1])
|
|
str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8;
|
|
else {
|
|
str_ptr += 16;
|
|
#if defined (FFCPS_DIFF1)
|
|
prev_data = orig_data;
|
|
#endif
|
|
continue;
|
|
}
|
|
|
|
match:;
|
|
if (str_ptr >= str_end)
|
|
/* Failed match. */
|
|
return NULL;
|
|
|
|
#if defined(FF_UTF)
|
|
if (utf_continue(str_ptr + IN_UCHARS(-offs1)))
|
|
{
|
|
/* Not a match. */
|
|
str_ptr += IN_UCHARS(1);
|
|
goto restart;
|
|
}
|
|
#endif
|
|
|
|
/* Match. */
|
|
#if defined (FFCPS)
|
|
str_ptr -= IN_UCHARS(offs1);
|
|
#endif
|
|
return str_ptr;
|
|
}
|
|
|
|
/* Failed match. */
|
|
return NULL;
|
|
}
|