Fix inifinite loop when a single byte newline is searched in JIT.

This commit is contained in:
Zoltán Herczeg 2020-05-29 14:20:23 +00:00
parent 5dfe817b5e
commit e0c6029a62
3 changed files with 36 additions and 14 deletions

View File

@ -9,6 +9,9 @@ compiler. This fixes https://bugs.exim.org/show_bug.cgi?id=2578. Patch for
Makefile.am and configure.ac by H.J. Lu. Equivalent patch for CMakeLists.txt Makefile.am and configure.ac by H.J. Lu. Equivalent patch for CMakeLists.txt
invented by PH. invented by PH.
2. Fix inifinite loop when a single byte newline is searched in JIT when
invalid utf8 mode is enabled.
Version 10.35 09-May-2020 Version 10.35 09-May-2020
--------------------------- ---------------------------

View File

@ -4578,7 +4578,14 @@ if (common->nltype != NLTYPE_ANY)
/* All newlines are ascii, just skip intermediate octets. */ /* All newlines are ascii, just skip intermediate octets. */
jump[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); jump[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
loop = LABEL(); loop = LABEL();
OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, TMP2, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)) == SLJIT_SUCCESS)
sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, TMP2, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
else
{
OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
}
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc0); OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc0);
CMPTO(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0x80, loop); CMPTO(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0x80, loop);
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));

View File

@ -1831,7 +1831,9 @@ struct invalid_utf8_regression_test_case {
const char *input; const char *input;
}; };
static struct invalid_utf8_regression_test_case invalid_utf8_regression_test_cases[] = { static const char invalid_utf8_newline_cr;
static const struct invalid_utf8_regression_test_case invalid_utf8_regression_test_cases[] = {
{ UDA, CI, 0, 0, 0, 0, 4, { ".", NULL }, "\xf4\x8f\xbf\xbf" }, { UDA, CI, 0, 0, 0, 0, 4, { ".", NULL }, "\xf4\x8f\xbf\xbf" },
{ UDA, CI, 0, 0, 0, 0, 4, { ".", NULL }, "\xf0\x90\x80\x80" }, { UDA, CI, 0, 0, 0, 0, 4, { ".", NULL }, "\xf0\x90\x80\x80" },
{ UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xf4\x90\x80\x80" }, { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xf4\x90\x80\x80" },
@ -1974,6 +1976,8 @@ static struct invalid_utf8_regression_test_case invalid_utf8_regression_test_cas
{ 0, PCRE2_JIT_COMPLETE, 0, 0, 1, -1, -1, { "\\X{2}", NULL }, "\r\n\n" }, { 0, PCRE2_JIT_COMPLETE, 0, 0, 1, -1, -1, { "\\X{2}", NULL }, "\r\n\n" },
{ 0, PCRE2_JIT_COMPLETE, 0, 0, 1, -1, -1, { "\\R{2}", NULL }, "\r\n\n" }, { 0, PCRE2_JIT_COMPLETE, 0, 0, 1, -1, -1, { "\\R{2}", NULL }, "\r\n\n" },
{ PCRE2_UTF | PCRE2_MULTILINE, CI, 0, 0, 0, -1, -1, { "^.a", &invalid_utf8_newline_cr }, "\xc3\xa7#a" },
{ 0, 0, 0, 0, 0, 0, 0, { NULL, NULL }, NULL } { 0, 0, 0, 0, 0, 0, 0, { NULL, NULL }, NULL }
}; };
@ -1981,7 +1985,7 @@ static struct invalid_utf8_regression_test_case invalid_utf8_regression_test_cas
#undef CI #undef CI
#undef CPI #undef CPI
static int run_invalid_utf8_test(struct invalid_utf8_regression_test_case *current, static int run_invalid_utf8_test(const struct invalid_utf8_regression_test_case *current,
int pattern_index, int i, pcre2_compile_context_8 *ccontext, pcre2_match_data_8 *mdata) int pattern_index, int i, pcre2_compile_context_8 *ccontext, pcre2_match_data_8 *mdata)
{ {
pcre2_code_8 *code; pcre2_code_8 *code;
@ -2034,7 +2038,7 @@ static int run_invalid_utf8_test(struct invalid_utf8_regression_test_case *curre
static int invalid_utf8_regression_tests(void) static int invalid_utf8_regression_tests(void)
{ {
struct invalid_utf8_regression_test_case *current; const struct invalid_utf8_regression_test_case *current;
pcre2_compile_context_8 *ccontext; pcre2_compile_context_8 *ccontext;
pcre2_match_data_8 *mdata; pcre2_match_data_8 *mdata;
int total = 0, successful = 0; int total = 0, successful = 0;
@ -2051,10 +2055,18 @@ static int invalid_utf8_regression_tests(void)
total++; total++;
result = 1; result = 1;
if (!run_invalid_utf8_test(current, total - 1, 0, ccontext, mdata)) if (current->pattern[1] != &invalid_utf8_newline_cr)
result = 0; {
if (!run_invalid_utf8_test(current, total - 1, 1, ccontext, mdata)) if (!run_invalid_utf8_test(current, total - 1, 0, ccontext, mdata))
result = 0; result = 0;
if (!run_invalid_utf8_test(current, total - 1, 1, ccontext, mdata))
result = 0;
} else {
pcre2_set_newline_8(ccontext, PCRE2_NEWLINE_CR);
if (!run_invalid_utf8_test(current, total - 1, 0, ccontext, mdata))
result = 0;
pcre2_set_newline_8(ccontext, PCRE2_NEWLINE_ANY);
}
if (result) { if (result) {
successful++; successful++;
@ -2128,7 +2140,7 @@ static PCRE2_UCHAR16 test16_10[] = { ' ', 0xdc00, 0xd800, 0x2028, '#', 0 };
static PCRE2_UCHAR16 test16_11[] = { 0xdc00, 0xdc00, 0xd800, 0xdc00, 0xdc00, '#', 0xd800, 0xdc00, '#', 0 }; static PCRE2_UCHAR16 test16_11[] = { 0xdc00, 0xdc00, 0xd800, 0xdc00, 0xdc00, '#', 0xd800, 0xdc00, '#', 0 };
static PCRE2_UCHAR16 test16_12[] = { '#', 0xd800, 0xdc00, 0xd800, '#', 0xd800, 0xdc00, 0xdc00, 0xdc00, '#', 0xd800, 0xdc00, '#', 0 }; static PCRE2_UCHAR16 test16_12[] = { '#', 0xd800, 0xdc00, 0xd800, '#', 0xd800, 0xdc00, 0xdc00, 0xdc00, '#', 0xd800, 0xdc00, '#', 0 };
static struct invalid_utf16_regression_test_case invalid_utf16_regression_test_cases[] = { static const struct invalid_utf16_regression_test_case invalid_utf16_regression_test_cases[] = {
{ UDA, CI, 0, 0, 0, 0, 1, { allany16, NULL }, test16_1 }, { UDA, CI, 0, 0, 0, 0, 1, { allany16, NULL }, test16_1 },
{ UDA, CI, 1, 0, 0, 1, 2, { allany16, NULL }, test16_1 }, { UDA, CI, 1, 0, 0, 1, 2, { allany16, NULL }, test16_1 },
{ UDA, CI, 2, 0, 0, 2, 3, { allany16, NULL }, test16_1 }, { UDA, CI, 2, 0, 0, 2, 3, { allany16, NULL }, test16_1 },
@ -2182,7 +2194,7 @@ static struct invalid_utf16_regression_test_case invalid_utf16_regression_test_c
#undef CI #undef CI
#undef CPI #undef CPI
static int run_invalid_utf16_test(struct invalid_utf16_regression_test_case *current, static int run_invalid_utf16_test(const struct invalid_utf16_regression_test_case *current,
int pattern_index, int i, pcre2_compile_context_16 *ccontext, pcre2_match_data_16 *mdata) int pattern_index, int i, pcre2_compile_context_16 *ccontext, pcre2_match_data_16 *mdata)
{ {
pcre2_code_16 *code; pcre2_code_16 *code;
@ -2242,7 +2254,7 @@ static int run_invalid_utf16_test(struct invalid_utf16_regression_test_case *cur
static int invalid_utf16_regression_tests(void) static int invalid_utf16_regression_tests(void)
{ {
struct invalid_utf16_regression_test_case *current; const struct invalid_utf16_regression_test_case *current;
pcre2_compile_context_16 *ccontext; pcre2_compile_context_16 *ccontext;
pcre2_match_data_16 *mdata; pcre2_match_data_16 *mdata;
int total = 0, successful = 0; int total = 0, successful = 0;
@ -2329,7 +2341,7 @@ static PCRE2_UCHAR32 test32_4[] = { '#', 0x10ffff, 0x110000, 0 };
static PCRE2_UCHAR32 test32_5[] = { ' ', 0x2028, '#', 0 }; static PCRE2_UCHAR32 test32_5[] = { ' ', 0x2028, '#', 0 };
static PCRE2_UCHAR32 test32_6[] = { ' ', 0x110000, 0x2028, '#', 0 }; static PCRE2_UCHAR32 test32_6[] = { ' ', 0x110000, 0x2028, '#', 0 };
static struct invalid_utf32_regression_test_case invalid_utf32_regression_test_cases[] = { static const struct invalid_utf32_regression_test_case invalid_utf32_regression_test_cases[] = {
{ UDA, CI, 0, 0, 0, 0, 1, { allany32, NULL }, test32_1 }, { UDA, CI, 0, 0, 0, 0, 1, { allany32, NULL }, test32_1 },
{ UDA, CI, 2, 0, 0, -1, -1, { allany32, NULL }, test32_1 }, { UDA, CI, 2, 0, 0, -1, -1, { allany32, NULL }, test32_1 },
{ UDA, CI, 0, 0, 0, 0, 1, { allany32, NULL }, test32_2 }, { UDA, CI, 0, 0, 0, 0, 1, { allany32, NULL }, test32_2 },
@ -2369,7 +2381,7 @@ static struct invalid_utf32_regression_test_case invalid_utf32_regression_test_c
#undef CI #undef CI
#undef CPI #undef CPI
static int run_invalid_utf32_test(struct invalid_utf32_regression_test_case *current, static int run_invalid_utf32_test(const struct invalid_utf32_regression_test_case *current,
int pattern_index, int i, pcre2_compile_context_32 *ccontext, pcre2_match_data_32 *mdata) int pattern_index, int i, pcre2_compile_context_32 *ccontext, pcre2_match_data_32 *mdata)
{ {
pcre2_code_32 *code; pcre2_code_32 *code;
@ -2429,7 +2441,7 @@ static int run_invalid_utf32_test(struct invalid_utf32_regression_test_case *cur
static int invalid_utf32_regression_tests(void) static int invalid_utf32_regression_tests(void)
{ {
struct invalid_utf32_regression_test_case *current; const struct invalid_utf32_regression_test_case *current;
pcre2_compile_context_32 *ccontext; pcre2_compile_context_32 *ccontext;
pcre2_match_data_32 *mdata; pcre2_match_data_32 *mdata;
int total = 0, successful = 0; int total = 0, successful = 0;