Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
systemsmanagement:saltstack:bundle:SLE11:deps
pcre2
pcre2-bsc1199235-CVE-2022-1587.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File pcre2-bsc1199235-CVE-2022-1587.patch of Package pcre2
diff --git a/ChangeLog b/ChangeLog index 5c1d44e..a9f3ef8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -682,6 +682,9 @@ Bugzilla #2232. 23. Fixed a unicode properrty matching issue in JIT. The character was not fully read in caseless matching. +24. Fixed an issue affecting recursions in JIT caused by duplicated data +transfers. + Version 10.30 14-August-2017 ---------------------------- diff --git a/src/pcre2_jit_compile.c b/src/pcre2_jit_compile.c index ee8c82b..950b653 100644 --- a/src/pcre2_jit_compile.c +++ b/src/pcre2_jit_compile.c @@ -407,6 +407,9 @@ typedef struct compiler_common { /* Locals used by fast fail optimization. */ sljit_s32 fast_fail_start_ptr; sljit_s32 fast_fail_end_ptr; + /* Variables used by recursive call generator. */ + sljit_s32 recurse_bitset_size; + uint8_t *recurse_bitset; /* Flipped and lower case tables. */ const sljit_u8 *fcc; @@ -2109,19 +2112,39 @@ for (i = 0; i < RECURSE_TMP_REG_COUNT; i++) #undef RECURSE_TMP_REG_COUNT +static BOOL recurse_check_bit(compiler_common *common, sljit_sw bit_index) +{ +uint8_t *byte; +uint8_t mask; + +SLJIT_ASSERT((bit_index & (sizeof(sljit_sw) - 1)) == 0); + +bit_index >>= SLJIT_WORD_SHIFT; + +mask = 1 << (bit_index & 0x7); +byte = common->recurse_bitset + (bit_index >> 3); + +if (*byte & mask) + return FALSE; + +*byte |= mask; +return TRUE; +} + static int get_recurse_data_length(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, BOOL *needs_control_head, BOOL *has_quit, BOOL *has_accept) { int length = 1; -int size; +int size, offset; PCRE2_SPTR alternative; BOOL quit_found = FALSE; BOOL accept_found = FALSE; BOOL setsom_found = FALSE; BOOL setmark_found = FALSE; -BOOL capture_last_found = FALSE; BOOL control_head_found = FALSE; +memset(common->recurse_bitset, 0, common->recurse_bitset_size); + #if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD SLJIT_ASSERT(common->control_head_ptr != 0); control_head_found = TRUE; @@ -2144,15 +2167,17 @@ while (cc < ccend) setsom_found = TRUE; if (common->mark_ptr != 0) setmark_found = TRUE; - if (common->capture_last_ptr != 0) - capture_last_found = TRUE; + if (common->capture_last_ptr != 0 && recurse_check_bit(common, common->capture_last_ptr)) + length++; cc += 1 + LINK_SIZE; break; case OP_KET: - if (PRIVATE_DATA(cc) != 0) + offset = PRIVATE_DATA(cc); + if (offset != 0) { - length++; + if (recurse_check_bit(common, offset)) + length++; SLJIT_ASSERT(PRIVATE_DATA(cc + 1) != 0); cc += PRIVATE_DATA(cc + 1); } @@ -2169,39 +2194,55 @@ while (cc < ccend) case OP_SBRA: case OP_SBRAPOS: case OP_SCOND: - length++; SLJIT_ASSERT(PRIVATE_DATA(cc) != 0); + if (recurse_check_bit(common, PRIVATE_DATA(cc))) + length++; cc += 1 + LINK_SIZE; break; case OP_CBRA: case OP_SCBRA: - length += 2; - if (common->capture_last_ptr != 0) - capture_last_found = TRUE; - if (common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0) + offset = GET2(cc, 1 + LINK_SIZE); + if (recurse_check_bit(common, OVECTOR(offset << 1))) + { + SLJIT_ASSERT(recurse_check_bit(common, OVECTOR((offset << 1) + 1))); + length += 2; + } + if (common->optimized_cbracket[offset] == 0 && recurse_check_bit(common, OVECTOR_PRIV(offset))) + length++; + if (common->capture_last_ptr != 0 && recurse_check_bit(common, common->capture_last_ptr)) length++; cc += 1 + LINK_SIZE + IMM2_SIZE; break; case OP_CBRAPOS: case OP_SCBRAPOS: - length += 2 + 2; - if (common->capture_last_ptr != 0) - capture_last_found = TRUE; + offset = GET2(cc, 1 + LINK_SIZE); + if (recurse_check_bit(common, OVECTOR(offset << 1))) + { + SLJIT_ASSERT(recurse_check_bit(common, OVECTOR((offset << 1) + 1))); + length += 2; + } + if (recurse_check_bit(common, OVECTOR_PRIV(offset))) + length++; + if (recurse_check_bit(common, PRIVATE_DATA(cc))) + length++; + if (common->capture_last_ptr != 0 && recurse_check_bit(common, common->capture_last_ptr)) + length++; cc += 1 + LINK_SIZE + IMM2_SIZE; break; case OP_COND: /* Might be a hidden SCOND. */ alternative = cc + GET(cc, 1); - if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN) + if ((*alternative == OP_KETRMAX || *alternative == OP_KETRMIN) && recurse_check_bit(common, PRIVATE_DATA(cc))) length++; cc += 1 + LINK_SIZE; break; CASE_ITERATOR_PRIVATE_DATA_1 - if (PRIVATE_DATA(cc) != 0) + offset = PRIVATE_DATA(cc); + if (offset != 0 && recurse_check_bit(common, offset)) length++; cc += 2; #ifdef SUPPORT_UNICODE @@ -2210,8 +2251,12 @@ while (cc < ccend) break; CASE_ITERATOR_PRIVATE_DATA_2A - if (PRIVATE_DATA(cc) != 0) + offset = PRIVATE_DATA(cc); + if (offset != 0 && recurse_check_bit(common, offset)) + { + SLJIT_ASSERT(recurse_check_bit(common, offset + sizeof(sljit_sw))); length += 2; + } cc += 2; #ifdef SUPPORT_UNICODE if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); @@ -2219,8 +2264,12 @@ while (cc < ccend) break; CASE_ITERATOR_PRIVATE_DATA_2B - if (PRIVATE_DATA(cc) != 0) + offset = PRIVATE_DATA(cc); + if (offset != 0 && recurse_check_bit(common, offset)) + { + SLJIT_ASSERT(recurse_check_bit(common, offset + sizeof(sljit_sw))); length += 2; + } cc += 2 + IMM2_SIZE; #ifdef SUPPORT_UNICODE if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); @@ -2228,20 +2277,29 @@ while (cc < ccend) break; CASE_ITERATOR_TYPE_PRIVATE_DATA_1 - if (PRIVATE_DATA(cc) != 0) + offset = PRIVATE_DATA(cc); + if (offset != 0 && recurse_check_bit(common, offset)) length++; cc += 1; break; CASE_ITERATOR_TYPE_PRIVATE_DATA_2A - if (PRIVATE_DATA(cc) != 0) + offset = PRIVATE_DATA(cc); + if (offset != 0 && recurse_check_bit(common, offset)) + { + SLJIT_ASSERT(recurse_check_bit(common, offset + sizeof(sljit_sw))); length += 2; + } cc += 1; break; CASE_ITERATOR_TYPE_PRIVATE_DATA_2B - if (PRIVATE_DATA(cc) != 0) + offset = PRIVATE_DATA(cc); + if (offset != 0 && recurse_check_bit(common, offset)) + { + SLJIT_ASSERT(recurse_check_bit(common, offset + sizeof(sljit_sw))); length += 2; + } cc += 1 + IMM2_SIZE; break; @@ -2253,7 +2311,9 @@ while (cc < ccend) #else size = 1 + 32 / (int)sizeof(PCRE2_UCHAR); #endif - if (PRIVATE_DATA(cc) != 0) + + offset = PRIVATE_DATA(cc); + if (offset != 0 && recurse_check_bit(common, offset)) length += get_class_iterator_size(cc + size); cc += size; break; @@ -2288,8 +2348,7 @@ while (cc < ccend) case OP_THEN: SLJIT_ASSERT(common->control_head_ptr != 0); quit_found = TRUE; - if (!control_head_found) - control_head_found = TRUE; + control_head_found = TRUE; cc++; break; @@ -2309,8 +2368,6 @@ SLJIT_ASSERT(cc == ccend); if (control_head_found) length++; -if (capture_last_found) - length++; if (quit_found) { if (setsom_found) @@ -2343,14 +2400,12 @@ sljit_sw shared_srcw[3]; sljit_sw kept_shared_srcw[2]; int private_count, shared_count, kept_shared_count; int from_sp, base_reg, offset, i; -BOOL setsom_found = FALSE; -BOOL setmark_found = FALSE; -BOOL capture_last_found = FALSE; -BOOL control_head_found = FALSE; + +memset(common->recurse_bitset, 0, common->recurse_bitset_size); #if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD SLJIT_ASSERT(common->control_head_ptr != 0); -control_head_found = TRUE; +recurse_check_bit(common, common->control_head_ptr); #endif switch (type) @@ -2438,11 +2493,10 @@ while (cc < ccend) { case OP_SET_SOM: SLJIT_ASSERT(common->has_set_som); - if (has_quit && !setsom_found) + if (has_quit && recurse_check_bit(common, OVECTOR(0))) { kept_shared_srcw[0] = OVECTOR(0); kept_shared_count = 1; - setsom_found = TRUE; } cc += 1; break; @@ -2450,33 +2504,31 @@ while (cc < ccend) case OP_RECURSE: if (has_quit) { - if (common->has_set_som && !setsom_found) + if (common->has_set_som && recurse_check_bit(common, OVECTOR(0))) { kept_shared_srcw[0] = OVECTOR(0); kept_shared_count = 1; - setsom_found = TRUE; } - if (common->mark_ptr != 0 && !setmark_found) + if (common->mark_ptr != 0 && recurse_check_bit(common, common->mark_ptr)) { kept_shared_srcw[kept_shared_count] = common->mark_ptr; kept_shared_count++; - setmark_found = TRUE; } } - if (common->capture_last_ptr != 0 && !capture_last_found) + if (common->capture_last_ptr != 0 && recurse_check_bit(common, common->capture_last_ptr)) { shared_srcw[0] = common->capture_last_ptr; shared_count = 1; - capture_last_found = TRUE; } cc += 1 + LINK_SIZE; break; case OP_KET: - if (PRIVATE_DATA(cc) != 0) + private_srcw[0] = PRIVATE_DATA(cc); + if (private_srcw[0] != 0) { - private_count = 1; - private_srcw[0] = PRIVATE_DATA(cc); + if (recurse_check_bit(common, private_srcw[0])) + private_count = 1; SLJIT_ASSERT(PRIVATE_DATA(cc + 1) != 0); cc += PRIVATE_DATA(cc + 1); } @@ -2493,50 +2545,66 @@ while (cc < ccend) case OP_SBRA: case OP_SBRAPOS: case OP_SCOND: - private_count = 1; private_srcw[0] = PRIVATE_DATA(cc); + if (recurse_check_bit(common, private_srcw[0])) + private_count = 1; cc += 1 + LINK_SIZE; break; case OP_CBRA: case OP_SCBRA: - offset = (GET2(cc, 1 + LINK_SIZE)) << 1; - shared_srcw[0] = OVECTOR(offset); - shared_srcw[1] = OVECTOR(offset + 1); - shared_count = 2; + offset = GET2(cc, 1 + LINK_SIZE); + shared_srcw[0] = OVECTOR(offset << 1); + if (recurse_check_bit(common, shared_srcw[0])) + { + shared_srcw[1] = shared_srcw[0] + sizeof(sljit_sw); + SLJIT_ASSERT(recurse_check_bit(common, shared_srcw[1])); + shared_count = 2; + } - if (common->capture_last_ptr != 0 && !capture_last_found) + if (common->capture_last_ptr != 0 && recurse_check_bit(common, common->capture_last_ptr)) { - shared_srcw[2] = common->capture_last_ptr; - shared_count = 3; - capture_last_found = TRUE; + shared_srcw[shared_count] = common->capture_last_ptr; + shared_count++; } - if (common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0) + if (common->optimized_cbracket[offset] == 0) { - private_count = 1; - private_srcw[0] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE)); + private_srcw[0] = OVECTOR_PRIV(offset); + if (recurse_check_bit(common, private_srcw[0])) + private_count = 1; } + cc += 1 + LINK_SIZE + IMM2_SIZE; break; case OP_CBRAPOS: case OP_SCBRAPOS: - offset = (GET2(cc, 1 + LINK_SIZE)) << 1; - shared_srcw[0] = OVECTOR(offset); - shared_srcw[1] = OVECTOR(offset + 1); - shared_count = 2; + offset = GET2(cc, 1 + LINK_SIZE); + shared_srcw[0] = OVECTOR(offset << 1); + if (recurse_check_bit(common, shared_srcw[0])) + { + shared_srcw[1] = shared_srcw[0] + sizeof(sljit_sw); + SLJIT_ASSERT(recurse_check_bit(common, shared_srcw[1])); + shared_count = 2; + } - if (common->capture_last_ptr != 0 && !capture_last_found) + if (common->capture_last_ptr != 0 && recurse_check_bit(common, common->capture_last_ptr)) { - shared_srcw[2] = common->capture_last_ptr; - shared_count = 3; - capture_last_found = TRUE; + shared_srcw[shared_count] = common->capture_last_ptr; + shared_count++; } - private_count = 2; private_srcw[0] = PRIVATE_DATA(cc); - private_srcw[1] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE)); + if (recurse_check_bit(common, private_srcw[0])) + private_count = 1; + + offset = OVECTOR_PRIV(offset); + if (recurse_check_bit(common, offset)) + { + private_srcw[private_count] = offset; + private_count++; + } cc += 1 + LINK_SIZE + IMM2_SIZE; break; @@ -2545,18 +2613,17 @@ while (cc < ccend) alternative = cc + GET(cc, 1); if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN) { - private_count = 1; private_srcw[0] = PRIVATE_DATA(cc); + if (recurse_check_bit(common, private_srcw[0])) + private_count = 1; } cc += 1 + LINK_SIZE; break; CASE_ITERATOR_PRIVATE_DATA_1 - if (PRIVATE_DATA(cc)) - { + private_srcw[0] = PRIVATE_DATA(cc); + if (private_srcw[0] != 0 && recurse_check_bit(common, private_srcw[0])) private_count = 1; - private_srcw[0] = PRIVATE_DATA(cc); - } cc += 2; #ifdef SUPPORT_UNICODE if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); @@ -2564,11 +2631,12 @@ while (cc < ccend) break; CASE_ITERATOR_PRIVATE_DATA_2A - if (PRIVATE_DATA(cc)) + private_srcw[0] = PRIVATE_DATA(cc); + if (private_srcw[0] != 0 && recurse_check_bit(common, private_srcw[0])) { private_count = 2; - private_srcw[0] = PRIVATE_DATA(cc); - private_srcw[1] = PRIVATE_DATA(cc) + sizeof(sljit_sw); + private_srcw[1] = private_srcw[0] + sizeof(sljit_sw); + SLJIT_ASSERT(recurse_check_bit(common, private_srcw[1])); } cc += 2; #ifdef SUPPORT_UNICODE @@ -2577,11 +2645,12 @@ while (cc < ccend) break; CASE_ITERATOR_PRIVATE_DATA_2B - if (PRIVATE_DATA(cc)) + private_srcw[0] = PRIVATE_DATA(cc); + if (private_srcw[0] != 0 && recurse_check_bit(common, private_srcw[0])) { private_count = 2; - private_srcw[0] = PRIVATE_DATA(cc); - private_srcw[1] = PRIVATE_DATA(cc) + sizeof(sljit_sw); + private_srcw[1] = private_srcw[0] + sizeof(sljit_sw); + SLJIT_ASSERT(recurse_check_bit(common, private_srcw[1])); } cc += 2 + IMM2_SIZE; #ifdef SUPPORT_UNICODE @@ -2590,30 +2659,30 @@ while (cc < ccend) break; CASE_ITERATOR_TYPE_PRIVATE_DATA_1 - if (PRIVATE_DATA(cc)) - { + private_srcw[0] = PRIVATE_DATA(cc); + if (private_srcw[0] != 0 && recurse_check_bit(common, private_srcw[0])) private_count = 1; - private_srcw[0] = PRIVATE_DATA(cc); - } cc += 1; break; CASE_ITERATOR_TYPE_PRIVATE_DATA_2A - if (PRIVATE_DATA(cc)) + private_srcw[0] = PRIVATE_DATA(cc); + if (private_srcw[0] != 0 && recurse_check_bit(common, private_srcw[0])) { private_count = 2; - private_srcw[0] = PRIVATE_DATA(cc); private_srcw[1] = private_srcw[0] + sizeof(sljit_sw); + SLJIT_ASSERT(recurse_check_bit(common, private_srcw[1])); } cc += 1; break; CASE_ITERATOR_TYPE_PRIVATE_DATA_2B - if (PRIVATE_DATA(cc)) + private_srcw[0] = PRIVATE_DATA(cc); + if (private_srcw[0] != 0 && recurse_check_bit(common, private_srcw[0])) { private_count = 2; - private_srcw[0] = PRIVATE_DATA(cc); private_srcw[1] = private_srcw[0] + sizeof(sljit_sw); + SLJIT_ASSERT(recurse_check_bit(common, private_srcw[1])); } cc += 1 + IMM2_SIZE; break; @@ -2630,14 +2699,17 @@ while (cc < ccend) switch(get_class_iterator_size(cc + i)) { case 1: - private_count = 1; private_srcw[0] = PRIVATE_DATA(cc); break; case 2: - private_count = 2; private_srcw[0] = PRIVATE_DATA(cc); - private_srcw[1] = private_srcw[0] + sizeof(sljit_sw); + if (recurse_check_bit(common, private_srcw[0])) + { + private_count = 2; + private_srcw[1] = private_srcw[0] + sizeof(sljit_sw); + SLJIT_ASSERT(recurse_check_bit(common, private_srcw[1])); + } break; default: @@ -2652,28 +2724,25 @@ while (cc < ccend) case OP_PRUNE_ARG: case OP_THEN_ARG: SLJIT_ASSERT(common->mark_ptr != 0); - if (has_quit && !setmark_found) + if (has_quit && recurse_check_bit(common, common->mark_ptr)) { kept_shared_srcw[0] = common->mark_ptr; kept_shared_count = 1; - setmark_found = TRUE; } - if (common->control_head_ptr != 0 && !control_head_found) + if (common->control_head_ptr != 0 && recurse_check_bit(common, common->control_head_ptr)) { shared_srcw[0] = common->control_head_ptr; shared_count = 1; - control_head_found = TRUE; } cc += 1 + 2 + cc[1]; break; case OP_THEN: SLJIT_ASSERT(common->control_head_ptr != 0); - if (!control_head_found) + if (recurse_check_bit(common, common->control_head_ptr)) { shared_srcw[0] = common->control_head_ptr; shared_count = 1; - control_head_found = TRUE; } cc++; break; @@ -2681,7 +2750,7 @@ while (cc < ccend) default: cc = next_opcode(common, cc); SLJIT_ASSERT(cc != NULL); - break; + continue; } if (type != recurse_copy_shared_to_global && type != recurse_copy_kept_shared_to_global) @@ -13262,7 +13331,7 @@ SLJIT_ASSERT(!(common->req_char_ptr != 0 && common->start_used_ptr != 0)); common->cbra_ptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_sw); total_length = ccend - common->start; -common->private_data_ptrs = (sljit_s32 *)SLJIT_MALLOC(total_length * (sizeof(sljit_s32) + (common->has_then ? 1 : 0)), allocator_data); +common->private_data_ptrs = (sljit_s32*)SLJIT_MALLOC(total_length * (sizeof(sljit_s32) + (common->has_then ? 1 : 0)), allocator_data); if (!common->private_data_ptrs) { SLJIT_FREE(common->optimized_cbracket, allocator_data); @@ -13304,6 +13373,7 @@ if (!compiler) common->compiler = compiler; /* Main pcre_jit_exec entry. */ +SLJIT_ASSERT((private_data_size & (sizeof(sljit_sw) - 1)) == 0); sljit_emit_enter(compiler, 0, SLJIT_ARG1(SW), 5, 5, 0, 0, private_data_size); /* Register init. */ @@ -13524,20 +13594,40 @@ common->fast_fail_end_ptr = 0; common->currententry = common->entries; common->local_quit_available = TRUE; quit_label = common->quit_label; -while (common->currententry != NULL) +if (common->currententry != NULL) { - /* Might add new entries. */ - compile_recurse(common); - if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) + /* A free bit for each private data. */ + common->recurse_bitset_size = ((private_data_size / (int)sizeof(sljit_sw)) + 7) >> 3; + SLJIT_ASSERT(common->recurse_bitset_size > 0); + common->recurse_bitset = (sljit_u8*)SLJIT_MALLOC(common->recurse_bitset_size, allocator_data);; + + if (common->recurse_bitset != NULL) + { + do + { + /* Might add new entries. */ + compile_recurse(common); + if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) + break; + flush_stubs(common); + common->currententry = common->currententry->next; + } + while (common->currententry != NULL); + + SLJIT_FREE(common->recurse_bitset, allocator_data); + } + + if (common->currententry != NULL) { + /* The common->recurse_bitset has been freed. */ + SLJIT_ASSERT(sljit_get_compiler_error(compiler) || common->recurse_bitset == NULL); + sljit_free_compiler(compiler); SLJIT_FREE(common->optimized_cbracket, allocator_data); SLJIT_FREE(common->private_data_ptrs, allocator_data); PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data); return PCRE2_ERROR_NOMEMORY; } - flush_stubs(common); - common->currententry = common->currententry->next; } common->local_quit_available = FALSE; common->quit_label = quit_label; diff --git a/src/pcre2_jit_test.c b/src/pcre2_jit_test.c index f581989..7c174a5 100644 --- a/src/pcre2_jit_test.c +++ b/src/pcre2_jit_test.c @@ -743,6 +743,7 @@ static struct regression_test_case regression_test_cases[] = { { MU, A, 0, 0, "((?(R)a|(?1)){1,3}?)M", "aaaM" }, { MU, A, 0, 0, "((.)(?:.|\\2(?1))){0}#(?1)#", "#aabbccdde# #aabbccddee#" }, { MU, A, 0, 0, "((.)(?:\\2|\\2{4}b)){0}#(?:(?1))+#", "#aaaab# #aaaaab#" }, + { MU, A, 0, 0 | F_NOMATCH, "(?1)$((.|\\2xx){1,2})", "abc" }, /* 16 bit specific tests. */ { CM, A, 0, 0 | F_FORCECONV, "\xc3\xa1", "\xc3\x81\xc3\xa1" },
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor