| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
|
|
| #include "pcre2_internal.h" |
|
|
|
|
|
|
| #define PTR_STACK_SIZE 20 |
|
|
| #define SUBSTITUTE_OPTIONS \ |
| (PCRE2_SUBSTITUTE_EXTENDED|PCRE2_SUBSTITUTE_GLOBAL| \ |
| PCRE2_SUBSTITUTE_LITERAL|PCRE2_SUBSTITUTE_MATCHED| \ |
| PCRE2_SUBSTITUTE_OVERFLOW_LENGTH|PCRE2_SUBSTITUTE_REPLACEMENT_ONLY| \ |
| PCRE2_SUBSTITUTE_UNKNOWN_UNSET|PCRE2_SUBSTITUTE_UNSET_EMPTY) |
|
|
|
|
|
|
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| static int |
| find_text_end(const pcre2_code *code, PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend, |
| BOOL last) |
| { |
| int rc = 0; |
| uint32_t nestlevel = 0; |
| BOOL literal = FALSE; |
| PCRE2_SPTR ptr = *ptrptr; |
|
|
| for (; ptr < ptrend; ptr++) |
| { |
| if (literal) |
| { |
| if (ptr[0] == CHAR_BACKSLASH && ptr < ptrend - 1 && ptr[1] == CHAR_E) |
| { |
| literal = FALSE; |
| ptr += 1; |
| } |
| } |
|
|
| else if (*ptr == CHAR_RIGHT_CURLY_BRACKET) |
| { |
| if (nestlevel == 0) goto EXIT; |
| nestlevel--; |
| } |
|
|
| else if (*ptr == CHAR_COLON && !last && nestlevel == 0) goto EXIT; |
|
|
| else if (*ptr == CHAR_DOLLAR_SIGN) |
| { |
| if (ptr < ptrend - 1 && ptr[1] == CHAR_LEFT_CURLY_BRACKET) |
| { |
| nestlevel++; |
| ptr += 1; |
| } |
| } |
|
|
| else if (*ptr == CHAR_BACKSLASH) |
| { |
| int erc; |
| int errorcode; |
| uint32_t ch; |
| PCRE2_SPTR esc_end_ptr; |
|
|
| if (ptr < ptrend - 1) switch (ptr[1]) |
| { |
| case CHAR_L: |
| case CHAR_l: |
| case CHAR_U: |
| case CHAR_u: |
| ptr += 1; |
| continue; |
| } |
|
|
| ptr += 1; |
| erc = PRIV(check_escape)(&ptr, ptrend, &ch, &errorcode, |
| code->overall_options, code->extra_options, code->top_bracket, FALSE, NULL); |
| if (errorcode != 0) |
| { |
| |
| |
| rc = PCRE2_ERROR_BADREPESCAPE; |
| goto EXIT; |
| } |
|
|
| esc_end_ptr = ptr; |
| ptr -= 1; |
|
|
| switch(erc) |
| { |
| case 0: |
| case ESC_b: |
| case ESC_v: |
| case ESC_E: |
| break; |
|
|
| case ESC_Q: |
| literal = TRUE; |
| break; |
|
|
| case ESC_g: |
| |
| |
| |
| |
| |
| |
| break; |
|
|
| default: |
| if (erc < 0) |
| break; |
| ptr = esc_end_ptr; |
| rc = PCRE2_ERROR_BADREPESCAPE; |
| goto EXIT; |
| } |
| } |
| } |
|
|
| rc = PCRE2_ERROR_REPMISSINGBRACE; |
|
|
| EXIT: |
| *ptrptr = ptr; |
| return rc; |
| } |
|
|
|
|
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| static BOOL |
| read_name_subst(PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend, BOOL utf, |
| const uint8_t* ctypes) |
| { |
| PCRE2_SPTR ptr = *ptrptr; |
| PCRE2_SPTR nameptr = ptr; |
|
|
| if (ptr >= ptrend) |
| goto FAILED; |
|
|
| |
| |
|
|
| |
| |
|
|
| #ifdef SUPPORT_UNICODE |
| if (utf) |
| { |
| uint32_t c, type; |
|
|
| while (ptr < ptrend) |
| { |
| GETCHAR(c, ptr); |
| type = UCD_CHARTYPE(c); |
| if (type != ucp_Nd && PRIV(ucp_gentype)[type] != ucp_L && |
| c != CHAR_UNDERSCORE) break; |
| ptr++; |
| FORWARDCHARTEST(ptr, ptrend); |
| } |
| } |
| else |
| #else |
| (void)utf; |
| #endif |
|
|
| |
|
|
| { |
| while (ptr < ptrend && MAX_255(*ptr) && (ctypes[*ptr] & ctype_word) != 0) |
| { |
| ptr++; |
| } |
| } |
|
|
| |
|
|
| if (ptr - nameptr > MAX_NAME_SIZE) |
| goto FAILED; |
|
|
| |
| if (ptr == nameptr) |
| goto FAILED; |
|
|
| *ptrptr = ptr; |
| return TRUE; |
|
|
| FAILED: |
| *ptrptr = ptr; |
| return FALSE; |
| } |
|
|
|
|
| |
| |
| |
|
|
| #define PCRE2_SUBSTITUTE_CASE_NONE 0 |
| |
| #define PCRE2_SUBSTITUTE_CASE_REVERSE_TITLE_FIRST 4 |
|
|
| typedef struct { |
| int to_case; |
| BOOL single_char; |
| } case_state; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| static PCRE2_SIZE |
| pessimistic_case_inflation(PCRE2_SIZE len) |
| { |
| return (len >> 3u) + 10; |
| } |
|
|
| |
|
|
| static PCRE2_SIZE |
| default_substitute_case_callout( |
| PCRE2_SPTR input, PCRE2_SIZE input_len, |
| PCRE2_UCHAR *output, PCRE2_SIZE output_cap, |
| case_state *state, const pcre2_code *code) |
| { |
| PCRE2_SPTR input_end = input + input_len; |
| #ifdef SUPPORT_UNICODE |
| BOOL utf; |
| BOOL ucp; |
| #endif |
| PCRE2_UCHAR temp[6]; |
| BOOL next_to_upper; |
| BOOL rest_to_upper; |
| BOOL single_char; |
| BOOL overflow = FALSE; |
| PCRE2_SIZE written = 0; |
|
|
| |
| |
| |
| |
| |
| PCRE2_ASSERT((char *)(input + input_len) <= (char *)output || |
| (char *)(output + output_cap) <= (char *)input); |
|
|
| #ifdef SUPPORT_UNICODE |
| utf = (code->overall_options & PCRE2_UTF) != 0; |
| ucp = (code->overall_options & PCRE2_UCP) != 0; |
| #endif |
|
|
| if (input_len == 0) return 0; |
|
|
| switch (state->to_case) |
| { |
| |
| default: |
| PCRE2_DEBUG_UNREACHABLE(); |
| return 0; |
| |
|
|
| case PCRE2_SUBSTITUTE_CASE_LOWER: |
| case PCRE2_SUBSTITUTE_CASE_UPPER: |
| next_to_upper = rest_to_upper = (state->to_case == PCRE2_SUBSTITUTE_CASE_UPPER); |
| break; |
|
|
| case PCRE2_SUBSTITUTE_CASE_TITLE_FIRST: |
| next_to_upper = TRUE; |
| rest_to_upper = FALSE; |
| state->to_case = PCRE2_SUBSTITUTE_CASE_LOWER; |
| break; |
|
|
| case PCRE2_SUBSTITUTE_CASE_REVERSE_TITLE_FIRST: |
| next_to_upper = FALSE; |
| rest_to_upper = TRUE; |
| state->to_case = PCRE2_SUBSTITUTE_CASE_UPPER; |
| break; |
| } |
|
|
| single_char = state->single_char; |
| if (single_char) |
| state->to_case = PCRE2_SUBSTITUTE_CASE_NONE; |
|
|
| while (input < input_end) |
| { |
| uint32_t ch; |
| unsigned int chlen; |
|
|
| GETCHARINCTEST(ch, input); |
|
|
| #ifdef SUPPORT_UNICODE |
| if ((utf || ucp) && ch >= 128) |
| { |
| uint32_t type = UCD_CHARTYPE(ch); |
| if (PRIV(ucp_gentype)[type] == ucp_L && |
| type != (next_to_upper? ucp_Lu : ucp_Ll)) |
| ch = UCD_OTHERCASE(ch); |
|
|
| |
| |
| |
| |
| |
| } |
| else |
| #endif |
| if (MAX_255(ch)) |
| { |
| if (((code->tables + cbits_offset + |
| (next_to_upper? cbit_upper:cbit_lower) |
| )[ch/8] & (1u << (ch%8))) == 0) |
| ch = (code->tables + fcc_offset)[ch]; |
| } |
|
|
| #ifdef SUPPORT_UNICODE |
| if (utf) chlen = PRIV(ord2utf)(ch, temp); else |
| #endif |
| { |
| temp[0] = ch; |
| chlen = 1; |
| } |
|
|
| if (!overflow && chlen <= output_cap) |
| { |
| memcpy(output, temp, CU2BYTES(chlen)); |
| output += chlen; |
| output_cap -= chlen; |
| } |
| else |
| { |
| overflow = TRUE; |
| } |
|
|
| if (chlen > ~(PCRE2_SIZE)0 - written) |
| return ~(PCRE2_SIZE)0; |
| written += chlen; |
|
|
| next_to_upper = rest_to_upper; |
|
|
| |
|
|
| if (single_char) |
| { |
| PCRE2_SIZE rest_len = input_end - input; |
|
|
| if (!overflow && rest_len <= output_cap) |
| memcpy(output, input, CU2BYTES(rest_len)); |
|
|
| if (rest_len > ~(PCRE2_SIZE)0 - written) |
| return ~(PCRE2_SIZE)0; |
| written += rest_len; |
|
|
| return written; |
| } |
| } |
|
|
| return written; |
| } |
|
|
| |
| |
| |
| |
| |
| |
|
|
| static PCRE2_SIZE |
| do_case_copy( |
| PCRE2_UCHAR *input_output, PCRE2_SIZE input_len, PCRE2_SIZE output_cap, |
| case_state *state, BOOL utf, |
| PCRE2_SIZE (*substitute_case_callout)(PCRE2_SPTR, PCRE2_SIZE, PCRE2_UCHAR *, |
| PCRE2_SIZE, int, void *), |
| void *substitute_case_callout_data) |
| { |
| PCRE2_SPTR input = input_output; |
| PCRE2_UCHAR *output = input_output; |
| PCRE2_SIZE rc; |
| PCRE2_SIZE rc2; |
| int ch1_to_case; |
| int rest_to_case; |
| PCRE2_UCHAR ch1[6]; |
| PCRE2_SIZE ch1_len; |
| PCRE2_SPTR rest; |
| PCRE2_SIZE rest_len; |
| BOOL ch1_overflow = FALSE; |
| BOOL rest_overflow = FALSE; |
|
|
| #if PCRE2_CODE_UNIT_WIDTH == 32 || !defined(SUPPORT_UNICODE) |
| (void)utf; |
| #endif |
|
|
| PCRE2_ASSERT(input_len != 0); |
|
|
| switch (state->to_case) |
| { |
| |
| default: |
| PCRE2_DEBUG_UNREACHABLE(); |
| return 0; |
| |
|
|
| case PCRE2_SUBSTITUTE_CASE_LOWER: |
| case PCRE2_SUBSTITUTE_CASE_UPPER: |
| case PCRE2_SUBSTITUTE_CASE_TITLE_FIRST: |
|
|
| |
| |
|
|
| if (state->single_char == FALSE) |
| { |
| rc = substitute_case_callout(input, input_len, output, output_cap, |
| state->to_case, substitute_case_callout_data); |
|
|
| if (state->to_case == PCRE2_SUBSTITUTE_CASE_TITLE_FIRST) |
| state->to_case = PCRE2_SUBSTITUTE_CASE_LOWER; |
|
|
| return rc; |
| } |
|
|
| ch1_to_case = state->to_case; |
| rest_to_case = PCRE2_SUBSTITUTE_CASE_NONE; |
| break; |
|
|
| case PCRE2_SUBSTITUTE_CASE_REVERSE_TITLE_FIRST: |
| ch1_to_case = PCRE2_SUBSTITUTE_CASE_LOWER; |
| rest_to_case = PCRE2_SUBSTITUTE_CASE_UPPER; |
| break; |
| } |
|
|
| |
| |
|
|
| { |
| PCRE2_SPTR ch_end = input; |
| uint32_t ch; |
|
|
| GETCHARINCTEST(ch, ch_end); |
| (void) ch; |
| PCRE2_ASSERT(ch_end <= input + input_len && ch_end - input <= 6); |
| ch1_len = ch_end - input; |
| memcpy(ch1, input, CU2BYTES(ch1_len)); |
| } |
|
|
| rest = input + ch1_len; |
| rest_len = input_len - ch1_len; |
|
|
| |
| |
| |
| |
| |
|
|
| { |
| PCRE2_SIZE ch1_cap; |
| PCRE2_SIZE max_ch1_cap; |
|
|
| ch1_cap = ch1_len; |
| PCRE2_ASSERT(output_cap >= input_len && input_len >= rest_len); |
| max_ch1_cap = output_cap - rest_len; |
|
|
| while (TRUE) |
| { |
| rc = substitute_case_callout(ch1, ch1_len, output, ch1_cap, ch1_to_case, |
| substitute_case_callout_data); |
| if (rc == ~(PCRE2_SIZE)0) return rc; |
|
|
| if (rc <= ch1_cap) break; |
|
|
| if (rc > max_ch1_cap) |
| { |
| ch1_overflow = TRUE; |
| break; |
| } |
|
|
| |
|
|
| memmove(input_output + rc, rest, CU2BYTES(rest_len)); |
| rest = input + rc; |
|
|
| ch1_cap = rc; |
|
|
| |
| |
| } |
| } |
|
|
| if (rest_to_case == PCRE2_SUBSTITUTE_CASE_NONE) |
| { |
| if (!ch1_overflow) |
| { |
| PCRE2_ASSERT(rest_len <= output_cap - rc); |
| memmove(output + rc, rest, CU2BYTES(rest_len)); |
| } |
| rc2 = rest_len; |
|
|
| state->to_case = PCRE2_SUBSTITUTE_CASE_NONE; |
| } |
| else |
| { |
| PCRE2_UCHAR dummy[1]; |
|
|
| rc2 = substitute_case_callout(rest, rest_len, |
| ch1_overflow? dummy : output + rc, |
| ch1_overflow? 0u : output_cap - rc, |
| rest_to_case, substitute_case_callout_data); |
| if (rc2 == ~(PCRE2_SIZE)0) return rc2; |
|
|
| if (!ch1_overflow && rc2 > output_cap - rc) rest_overflow = TRUE; |
|
|
| |
| |
| |
| |
| |
| |
| if (ch1_overflow && rc2 < rest_len) |
| rc2 = rest_len; |
|
|
| state->to_case = PCRE2_SUBSTITUTE_CASE_UPPER; |
| } |
|
|
| if (rc2 > ~(PCRE2_SIZE)0 - rc) |
| return ~(PCRE2_SIZE)0; |
|
|
| PCRE2_ASSERT(!(ch1_overflow || rest_overflow) || rc + rc2 > output_cap); |
| (void)rest_overflow; |
|
|
| return rc + rc2; |
| } |
|
|
|
|
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
|
|
| #define CHECKMEMCPY(from, length_) \ |
| do { \ |
| PCRE2_SIZE chkmc_length = length_; \ |
| if (overflowed) \ |
| { \ |
| if (chkmc_length > ~(PCRE2_SIZE)0 - extra_needed) \ |
| goto TOOLARGEREPLACE; \ |
| extra_needed += chkmc_length; \ |
| } \ |
| else if (lengthleft < chkmc_length) \ |
| { \ |
| if ((suboptions & PCRE2_SUBSTITUTE_OVERFLOW_LENGTH) == 0) goto NOROOM; \ |
| overflowed = TRUE; \ |
| extra_needed = chkmc_length - lengthleft; \ |
| } \ |
| else \ |
| { \ |
| memcpy(buffer + buff_offset, from, CU2BYTES(chkmc_length)); \ |
| buff_offset += chkmc_length; \ |
| lengthleft -= chkmc_length; \ |
| } \ |
| } \ |
| while (0) |
|
|
| |
| |
| |
| |
| |
|
|
| #define CHECKCASECPY_BASE(length_, do_call) \ |
| do { \ |
| PCRE2_SIZE chkcc_length = (PCRE2_SIZE)(length_); \ |
| PCRE2_SIZE chkcc_rc; \ |
| do_call \ |
| if (lengthleft < chkcc_rc) \ |
| { \ |
| if ((suboptions & PCRE2_SUBSTITUTE_OVERFLOW_LENGTH) == 0) goto NOROOM; \ |
| overflowed = TRUE; \ |
| extra_needed = chkcc_rc - lengthleft; \ |
| } \ |
| else \ |
| { \ |
| buff_offset += chkcc_rc; \ |
| lengthleft -= chkcc_rc; \ |
| } \ |
| } \ |
| while (0) |
|
|
| #define CHECKCASECPY_DEFAULT(from, length_) \ |
| CHECKCASECPY_BASE(length_, { \ |
| chkcc_rc = default_substitute_case_callout(from, chkcc_length, \ |
| buffer + buff_offset, \ |
| overflowed? 0 : lengthleft, \ |
| &forcecase, code); \ |
| if (overflowed) \ |
| { \ |
| if (chkcc_rc > ~(PCRE2_SIZE)0 - extra_needed) \ |
| goto TOOLARGEREPLACE; \ |
| extra_needed += chkcc_rc; \ |
| break; \ |
| } \ |
| }) |
|
|
| #define CHECKCASECPY_CALLOUT(length_) \ |
| CHECKCASECPY_BASE(length_, { \ |
| chkcc_rc = do_case_copy(buffer + buff_offset, chkcc_length, \ |
| lengthleft, &forcecase, utf, \ |
| substitute_case_callout, \ |
| substitute_case_callout_data); \ |
| if (chkcc_rc == ~(PCRE2_SIZE)0) goto CASEERROR; \ |
| }) |
|
|
| |
| |
|
|
| #define DELAYEDFORCECASE() \ |
| do { \ |
| PCRE2_SIZE chars_outstanding = (buff_offset - casestart_offset) + \ |
| (extra_needed - casestart_extra_needed); \ |
| if (chars_outstanding > 0) \ |
| { \ |
| if (overflowed) \ |
| { \ |
| PCRE2_SIZE guess = pessimistic_case_inflation(chars_outstanding); \ |
| if (guess > ~(PCRE2_SIZE)0 - extra_needed) \ |
| goto TOOLARGEREPLACE; \ |
| extra_needed += guess; \ |
| } \ |
| else \ |
| { \ |
| \ |
| lengthleft += (buff_offset - casestart_offset); \ |
| buff_offset = casestart_offset; \ |
| \ |
| CHECKCASECPY_CALLOUT(chars_outstanding); \ |
| } \ |
| } \ |
| } \ |
| while (0) |
|
|
|
|
| |
|
|
| PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION |
| pcre2_substitute(const pcre2_code *code, PCRE2_SPTR subject, PCRE2_SIZE length, |
| PCRE2_SIZE start_offset, uint32_t options, pcre2_match_data *match_data, |
| pcre2_match_context *mcontext, PCRE2_SPTR replacement, PCRE2_SIZE rlength, |
| PCRE2_UCHAR *buffer, PCRE2_SIZE *blength) |
| { |
| int rc; |
| int subs; |
| uint32_t ovector_count; |
| uint32_t goptions = 0; |
| uint32_t suboptions; |
| pcre2_match_data *internal_match_data = NULL; |
| BOOL escaped_literal = FALSE; |
| BOOL overflowed = FALSE; |
| BOOL use_existing_match; |
| BOOL replacement_only; |
| BOOL utf = (code->overall_options & PCRE2_UTF) != 0; |
| PCRE2_UCHAR temp[6]; |
| PCRE2_UCHAR null_str[1] = { 0xcd }; |
| PCRE2_SPTR original_subject = subject; |
| PCRE2_SPTR ptr; |
| PCRE2_SPTR repend = NULL; |
| PCRE2_SIZE extra_needed = 0; |
| PCRE2_SIZE buff_offset, buff_length, lengthleft, fraglength; |
| PCRE2_SIZE *ovector; |
| PCRE2_SIZE ovecsave[2] = { 0, 0 }; |
| pcre2_substitute_callout_block scb; |
| PCRE2_SIZE sub_start_extra_needed; |
| PCRE2_SIZE (*substitute_case_callout)(PCRE2_SPTR, PCRE2_SIZE, PCRE2_UCHAR *, |
| PCRE2_SIZE, int, void *) = NULL; |
| void *substitute_case_callout_data = NULL; |
|
|
| |
|
|
| buff_offset = 0; |
| lengthleft = buff_length = *blength; |
| *blength = PCRE2_UNSET; |
|
|
| if (mcontext != NULL) |
| { |
| substitute_case_callout = mcontext->substitute_case_callout; |
| substitute_case_callout_data = mcontext->substitute_case_callout_data; |
| } |
|
|
| |
| |
|
|
| if ((options & (PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT)) != 0) |
| return PCRE2_ERROR_BADOPTION; |
|
|
| |
| |
|
|
| if (replacement == NULL) |
| { |
| if (rlength != 0) return PCRE2_ERROR_NULL; |
| replacement = null_str; |
| } |
|
|
| if (rlength == PCRE2_ZERO_TERMINATED) rlength = PRIV(strlen)(replacement); |
| repend = replacement + rlength; |
|
|
| |
|
|
| if (subject == NULL) |
| { |
| if (length != 0) return PCRE2_ERROR_NULL; |
| subject = null_str; |
| } |
|
|
| if (length == PCRE2_ZERO_TERMINATED) length = PRIV(strlen)(subject); |
|
|
| |
| |
|
|
| use_existing_match = ((options & PCRE2_SUBSTITUTE_MATCHED) != 0); |
| replacement_only = ((options & PCRE2_SUBSTITUTE_REPLACEMENT_ONLY) != 0); |
|
|
| if (use_existing_match && match_data == NULL) return PCRE2_ERROR_NULL; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| if (use_existing_match) |
| { |
| |
| |
| |
| if (match_data->rc < 0 && match_data->rc != PCRE2_ERROR_NOMATCH) |
| return match_data->rc; |
|
|
| |
| if (match_data->matchedby == PCRE2_MATCHEDBY_DFA_INTERPRETER) |
| return PCRE2_ERROR_DFA_UFUNC; |
|
|
| if (code != match_data->code) |
| return PCRE2_ERROR_DIFFSUBSPATTERN; |
|
|
| |
| |
| |
| |
| if (length != match_data->subject_length || |
| !(original_subject == match_data->subject || |
| ((match_data->flags & PCRE2_MD_COPIED_SUBJECT) != 0 && |
| (length == 0 || |
| memcmp(subject, match_data->subject, CU2BYTES(length)) == 0)))) |
| return PCRE2_ERROR_DIFFSUBSSUBJECT; |
|
|
| if (start_offset != match_data->start_offset) |
| return PCRE2_ERROR_DIFFSUBSOFFSET; |
|
|
| if ((options & ~(SUBSTITUTE_OPTIONS|PCRE2_NO_UTF_CHECK)) != |
| (match_data->options & ~PCRE2_NO_UTF_CHECK)) |
| return PCRE2_ERROR_DIFFSUBSOPTIONS; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
|
|
| if (match_data == NULL) |
| { |
| pcre2_general_context gcontext; |
| gcontext.memctl = (mcontext == NULL)? |
| ((pcre2_real_code *)code)->memctl : |
| ((pcre2_real_match_context *)mcontext)->memctl; |
| match_data = internal_match_data = |
| pcre2_match_data_create_from_pattern(code, &gcontext); |
| if (internal_match_data == NULL) return PCRE2_ERROR_NOMEMORY; |
| } |
|
|
| else if (use_existing_match) |
| { |
| int pairs; |
| pcre2_general_context gcontext; |
| gcontext.memctl = (mcontext == NULL)? |
| ((pcre2_real_code *)code)->memctl : |
| ((pcre2_real_match_context *)mcontext)->memctl; |
| pairs = (code->top_bracket + 1 < match_data->oveccount)? |
| code->top_bracket + 1 : match_data->oveccount; |
| internal_match_data = pcre2_match_data_create(match_data->oveccount, |
| &gcontext); |
| if (internal_match_data == NULL) return PCRE2_ERROR_NOMEMORY; |
| memcpy(internal_match_data, match_data, offsetof(pcre2_match_data, ovector) |
| + 2*pairs*sizeof(PCRE2_SIZE)); |
| internal_match_data->heapframes = NULL; |
| internal_match_data->heapframes_size = 0; |
| |
| internal_match_data->flags &= ~PCRE2_MD_COPIED_SUBJECT; |
| match_data = internal_match_data; |
| } |
|
|
| |
|
|
| if (internal_match_data != NULL) options &= ~PCRE2_COPY_MATCHED_SUBJECT; |
|
|
| |
|
|
| ovector = pcre2_get_ovector_pointer(match_data); |
| ovector_count = pcre2_get_ovector_count(match_data); |
|
|
| |
|
|
| scb.version = 0; |
| scb.input = subject; |
| scb.output = (PCRE2_SPTR)buffer; |
| scb.ovector = ovector; |
|
|
| |
|
|
| #ifdef SUPPORT_UNICODE |
| if (utf && (options & PCRE2_NO_UTF_CHECK) == 0) |
| { |
| rc = PRIV(valid_utf)(replacement, rlength, &(match_data->startchar)); |
| if (rc != 0) |
| { |
| match_data->leftchar = 0; |
| goto EXIT; |
| } |
| } |
| #endif |
|
|
| |
|
|
| suboptions = options & SUBSTITUTE_OPTIONS; |
| options &= ~SUBSTITUTE_OPTIONS; |
|
|
| |
|
|
| if (start_offset > length) |
| { |
| match_data->leftchar = 0; |
| rc = PCRE2_ERROR_BADOFFSET; |
| goto EXIT; |
| } |
|
|
| |
|
|
| if (!replacement_only) CHECKMEMCPY(subject, start_offset); |
|
|
| |
| |
|
|
| subs = 0; |
| for (;;) |
| { |
| PCRE2_SPTR ptrstack[PTR_STACK_SIZE]; |
| uint32_t ptrstackptr = 0; |
| case_state forcecase = { PCRE2_SUBSTITUTE_CASE_NONE, FALSE }; |
| PCRE2_SIZE casestart_offset = 0; |
| PCRE2_SIZE casestart_extra_needed = 0; |
|
|
| if (use_existing_match) |
| { |
| rc = match_data->rc; |
| use_existing_match = FALSE; |
| } |
| else rc = pcre2_match(code, subject, length, start_offset, options|goptions, |
| match_data, mcontext); |
|
|
| #ifdef SUPPORT_UNICODE |
| if (utf) options |= PCRE2_NO_UTF_CHECK; |
| #endif |
|
|
| |
| |
|
|
| if (rc == PCRE2_ERROR_NOMATCH) break; |
|
|
| if (rc < 0) goto EXIT; |
|
|
| |
| |
|
|
| if (ovector[1] < ovector[0] || ovector[0] < start_offset) |
| { |
| rc = PCRE2_ERROR_BADSUBSPATTERN; |
| goto EXIT; |
| } |
|
|
| |
| |
| |
| |
| |
| |
|
|
| |
| if (subs > 0 && |
| !(ovector[1] > ovecsave[1] || |
| (ovector[1] == ovector[0] && ovecsave[1] > ovecsave[0] && |
| ovector[1] == ovecsave[1]))) |
| { |
| PCRE2_DEBUG_UNREACHABLE(); |
| rc = PCRE2_ERROR_INTERNAL_DUPMATCH; |
| goto EXIT; |
| } |
| |
|
|
| ovecsave[0] = ovector[0]; |
| ovecsave[1] = ovector[1]; |
|
|
| |
| |
|
|
| if (subs == INT_MAX) |
| { |
| rc = PCRE2_ERROR_TOOMANYREPLACE; |
| goto EXIT; |
| } |
| subs++; |
|
|
| |
| |
| |
|
|
| if (rc == 0) rc = ovector_count; |
| fraglength = ovector[0] - start_offset; |
| if (!replacement_only) CHECKMEMCPY(subject + start_offset, fraglength); |
| scb.output_offsets[0] = buff_offset; |
| scb.oveccount = rc; |
| sub_start_extra_needed = extra_needed; |
|
|
| |
| |
|
|
| ptr = replacement; |
| if ((suboptions & PCRE2_SUBSTITUTE_LITERAL) != 0) |
| { |
| CHECKMEMCPY(ptr, rlength); |
| } |
|
|
| |
| |
| |
| |
|
|
| else for (;;) |
| { |
| uint32_t ch; |
| unsigned int chlen; |
| int group; |
| uint32_t special; |
| PCRE2_SPTR text1_start = NULL; |
| PCRE2_SPTR text1_end = NULL; |
| PCRE2_SPTR text2_start = NULL; |
| PCRE2_SPTR text2_end = NULL; |
| PCRE2_UCHAR name[MAX_NAME_SIZE + 1]; |
|
|
| |
|
|
| if (ptr >= repend) |
| { |
| if (ptrstackptr == 0) break; |
| repend = ptrstack[--ptrstackptr]; |
| ptr = ptrstack[--ptrstackptr]; |
| continue; |
| } |
|
|
| |
|
|
| if (escaped_literal) |
| { |
| if (ptr[0] == CHAR_BACKSLASH && ptr < repend - 1 && ptr[1] == CHAR_E) |
| { |
| escaped_literal = FALSE; |
| ptr += 2; |
| continue; |
| } |
| goto LOADLITERAL; |
| } |
|
|
| |
|
|
| if (*ptr == CHAR_DOLLAR_SIGN) |
| { |
| BOOL inparens; |
| BOOL inangle; |
| BOOL star; |
| PCRE2_SIZE sublength; |
| PCRE2_UCHAR next; |
| PCRE2_SPTR subptr, subptrend; |
|
|
| if (++ptr >= repend) goto BAD; |
| if ((next = *ptr) == CHAR_DOLLAR_SIGN) goto LOADLITERAL; |
|
|
| special = 0; |
| text1_start = NULL; |
| text1_end = NULL; |
| text2_start = NULL; |
| text2_end = NULL; |
| group = -1; |
| inparens = FALSE; |
| inangle = FALSE; |
| star = FALSE; |
| subptr = NULL; |
| subptrend = NULL; |
|
|
| |
| if (next == CHAR_AMPERSAND) |
| { |
| ++ptr; |
| group = 0; |
| goto GROUP_SUBSTITUTE; |
| } |
| if (next == CHAR_GRAVE_ACCENT || next == CHAR_APOSTROPHE) |
| { |
| ++ptr; |
| rc = pcre2_substring_length_bynumber(match_data, 0, &sublength); |
| if (rc < 0) goto PTREXIT; |
|
|
| if (next == CHAR_GRAVE_ACCENT) |
| { |
| subptr = subject; |
| subptrend = subject + ovector[0]; |
| } |
| else |
| { |
| subptr = subject + ovector[1]; |
| subptrend = subject + length; |
| } |
|
|
| goto SUBPTR_SUBSTITUTE; |
| } |
| if (next == CHAR_UNDERSCORE) |
| { |
| |
| ++ptr; |
| subptr = subject; |
| subptrend = subject + length; |
| goto SUBPTR_SUBSTITUTE; |
| } |
| else if (next == CHAR_PLUS && |
| !(ptr+1 < repend && ptr[1] == CHAR_LEFT_CURLY_BRACKET)) |
| { |
| |
| |
| |
| ++ptr; |
| if (code->top_bracket == 0) |
| { |
| |
| |
| if ((suboptions & PCRE2_SUBSTITUTE_UNKNOWN_UNSET) == 0) |
| { |
| rc = PCRE2_ERROR_NOSUBSTRING; |
| goto PTREXIT; |
| } |
| group = 0; |
| } |
| else |
| { |
| |
| |
| if (match_data->oveccount < code->top_bracket + 1) |
| { |
| rc = PCRE2_ERROR_UNAVAILABLE; |
| goto PTREXIT; |
| } |
| for (group = code->top_bracket; group > 0; group--) |
| if (ovector[2*group] != PCRE2_UNSET) break; |
| } |
| if (group == 0) |
| { |
| if ((suboptions & PCRE2_SUBSTITUTE_UNSET_EMPTY) != 0) continue; |
| rc = PCRE2_ERROR_UNSET; |
| goto PTREXIT; |
| } |
| goto GROUP_SUBSTITUTE; |
| } |
|
|
| if (next == CHAR_LEFT_CURLY_BRACKET) |
| { |
| if (++ptr >= repend) goto BAD; |
| next = *ptr; |
| inparens = TRUE; |
| } |
| else if (next == CHAR_LESS_THAN_SIGN) |
| { |
| |
| |
| |
| if (++ptr >= repend) goto BAD; |
| next = *ptr; |
| inangle = TRUE; |
| } |
|
|
| if (!inangle && next == CHAR_ASTERISK) |
| { |
| if (++ptr >= repend) goto BAD; |
| next = *ptr; |
| star = TRUE; |
| } |
|
|
| if (!star && !inangle && next >= CHAR_0 && next <= CHAR_9) |
| { |
| group = next - CHAR_0; |
| while (++ptr < repend) |
| { |
| next = *ptr; |
| if (next < CHAR_0 || next > CHAR_9) break; |
| group = group * 10 + (next - CHAR_0); |
|
|
| |
| |
| |
| |
|
|
| if (group > code->top_bracket) |
| { |
| if ((suboptions & PCRE2_SUBSTITUTE_UNKNOWN_UNSET) != 0) |
| { |
| while (++ptr < repend && *ptr >= CHAR_0 && *ptr <= CHAR_9); |
| break; |
| } |
| else |
| { |
| rc = PCRE2_ERROR_NOSUBSTRING; |
| goto PTREXIT; |
| } |
| } |
| } |
| } |
| else |
| { |
| PCRE2_SIZE name_len; |
| PCRE2_SPTR name_start = ptr; |
| if (!read_name_subst(&ptr, repend, utf, code->tables + ctypes_offset)) |
| goto BAD; |
| name_len = ptr - name_start; |
| memcpy(name, name_start, CU2BYTES(name_len)); |
| name[name_len] = 0; |
| } |
|
|
| next = 0; |
| (void)next; |
|
|
| |
| |
|
|
| if (inparens) |
| { |
| if ((suboptions & PCRE2_SUBSTITUTE_EXTENDED) != 0 && |
| !star && ptr < repend - 2 && *ptr == CHAR_COLON) |
| { |
| special = *(++ptr); |
| if (special != CHAR_PLUS && special != CHAR_MINUS) |
| { |
| rc = PCRE2_ERROR_BADSUBSTITUTION; |
| goto PTREXIT; |
| } |
|
|
| text1_start = ++ptr; |
| rc = find_text_end(code, &ptr, repend, special == CHAR_MINUS); |
| if (rc != 0) goto PTREXIT; |
| text1_end = ptr; |
|
|
| if (special == CHAR_PLUS && *ptr == CHAR_COLON) |
| { |
| text2_start = ++ptr; |
| rc = find_text_end(code, &ptr, repend, TRUE); |
| if (rc != 0) goto PTREXIT; |
| text2_end = ptr; |
| } |
| } |
|
|
| else |
| { |
| if (ptr >= repend || *ptr != CHAR_RIGHT_CURLY_BRACKET) |
| { |
| rc = PCRE2_ERROR_REPMISSINGBRACE; |
| goto PTREXIT; |
| } |
| } |
|
|
| ptr++; |
| } |
|
|
| if (inangle) |
| { |
| if (ptr >= repend || *ptr != CHAR_GREATER_THAN_SIGN) |
| goto BAD; |
| ptr++; |
| } |
|
|
| |
| |
|
|
| if (star) |
| { |
| if (PRIV(strcmp_c8)(name, STRING_MARK) == 0) |
| { |
| PCRE2_SPTR mark = pcre2_get_mark(match_data); |
| if (mark != NULL) |
| { |
| |
| |
| fraglength = mark[-1]; |
| if (forcecase.to_case != PCRE2_SUBSTITUTE_CASE_NONE && |
| substitute_case_callout == NULL) |
| CHECKCASECPY_DEFAULT(mark, fraglength); |
| else |
| CHECKMEMCPY(mark, fraglength); |
| } |
| } |
| else goto BAD; |
| } |
|
|
| |
| |
|
|
| else |
| { |
| GROUP_SUBSTITUTE: |
| |
| |
| |
| |
|
|
| if (group < 0) |
| { |
| PCRE2_SPTR first, last, entry; |
| rc = pcre2_substring_nametable_scan(code, name, &first, &last); |
| if (rc == PCRE2_ERROR_NOSUBSTRING && |
| (suboptions & PCRE2_SUBSTITUTE_UNKNOWN_UNSET) != 0) |
| { |
| group = code->top_bracket + 1; |
| } |
| else |
| { |
| if (rc < 0) goto PTREXIT; |
| for (entry = first; entry <= last; entry += rc) |
| { |
| uint32_t ng = GET2(entry, 0); |
| if (ng < ovector_count) |
| { |
| if (group < 0) group = ng; |
| if (ovector[ng*2] != PCRE2_UNSET) |
| { |
| group = ng; |
| break; |
| } |
| } |
| } |
|
|
| |
| |
|
|
| if (group < 0) group = GET2(first, 0); |
| } |
| } |
|
|
| |
| |
| |
|
|
| rc = pcre2_substring_length_bynumber(match_data, group, &sublength); |
| if (rc < 0) |
| { |
| if (rc == PCRE2_ERROR_NOSUBSTRING && |
| (suboptions & PCRE2_SUBSTITUTE_UNKNOWN_UNSET) != 0) |
| { |
| rc = PCRE2_ERROR_UNSET; |
| } |
| if (rc != PCRE2_ERROR_UNSET) goto PTREXIT; |
| if (special == 0) |
| { |
| if ((suboptions & PCRE2_SUBSTITUTE_UNSET_EMPTY) != 0) continue; |
| goto PTREXIT; |
| } |
| } |
|
|
| |
| |
| |
|
|
| if (special != 0) |
| { |
| if (special == CHAR_MINUS) |
| { |
| if (rc == 0) goto LITERAL_SUBSTITUTE; |
| text2_start = text1_start; |
| text2_end = text1_end; |
| } |
|
|
| if (ptrstackptr >= PTR_STACK_SIZE) goto BAD; |
| ptrstack[ptrstackptr++] = ptr; |
| ptrstack[ptrstackptr++] = repend; |
|
|
| if (rc == 0) |
| { |
| ptr = text1_start; |
| repend = text1_end; |
| } |
| else |
| { |
| ptr = text2_start; |
| repend = text2_end; |
| } |
| continue; |
| } |
|
|
| |
|
|
| LITERAL_SUBSTITUTE: |
| subptr = subject + ovector[group*2]; |
| subptrend = subject + ovector[group*2 + 1]; |
|
|
| |
|
|
| SUBPTR_SUBSTITUTE: |
| if (forcecase.to_case != PCRE2_SUBSTITUTE_CASE_NONE && |
| substitute_case_callout == NULL) |
| CHECKCASECPY_DEFAULT(subptr, subptrend - subptr); |
| else |
| CHECKMEMCPY(subptr, subptrend - subptr); |
| } |
| } |
|
|
| |
| |
| |
| |
|
|
| else if ((suboptions & PCRE2_SUBSTITUTE_EXTENDED) != 0 && |
| *ptr == CHAR_BACKSLASH) |
| { |
| int errorcode; |
| case_state new_forcecase = { PCRE2_SUBSTITUTE_CASE_NONE, FALSE }; |
|
|
| if (ptr < repend - 1) switch (ptr[1]) |
| { |
| case CHAR_L: |
| new_forcecase.to_case = PCRE2_SUBSTITUTE_CASE_LOWER; |
| new_forcecase.single_char = FALSE; |
| ptr += 2; |
| break; |
|
|
| case CHAR_l: |
| new_forcecase.to_case = PCRE2_SUBSTITUTE_CASE_LOWER; |
| new_forcecase.single_char = TRUE; |
| ptr += 2; |
| if (ptr + 2 < repend && ptr[0] == CHAR_BACKSLASH && ptr[1] == CHAR_U) |
| { |
| |
| new_forcecase.to_case = PCRE2_SUBSTITUTE_CASE_REVERSE_TITLE_FIRST; |
| new_forcecase.single_char = FALSE; |
| ptr += 2; |
| } |
| break; |
|
|
| case CHAR_U: |
| new_forcecase.to_case = PCRE2_SUBSTITUTE_CASE_UPPER; |
| new_forcecase.single_char = FALSE; |
| ptr += 2; |
| break; |
|
|
| case CHAR_u: |
| new_forcecase.to_case = PCRE2_SUBSTITUTE_CASE_TITLE_FIRST; |
| new_forcecase.single_char = TRUE; |
| ptr += 2; |
| if (ptr + 2 < repend && ptr[0] == CHAR_BACKSLASH && ptr[1] == CHAR_L) |
| { |
| |
| new_forcecase.to_case = PCRE2_SUBSTITUTE_CASE_TITLE_FIRST; |
| new_forcecase.single_char = FALSE; |
| ptr += 2; |
| } |
| break; |
|
|
| default: |
| break; |
| } |
|
|
| if (new_forcecase.to_case != PCRE2_SUBSTITUTE_CASE_NONE) |
| { |
| SETFORCECASE: |
|
|
| |
| |
| |
| |
| |
|
|
| if (substitute_case_callout != NULL && |
| forcecase.to_case != PCRE2_SUBSTITUTE_CASE_NONE) |
| DELAYEDFORCECASE(); |
|
|
| forcecase = new_forcecase; |
| casestart_offset = buff_offset; |
| casestart_extra_needed = extra_needed; |
| continue; |
| } |
|
|
| ptr++; |
| rc = PRIV(check_escape)(&ptr, repend, &ch, &errorcode, |
| code->overall_options, code->extra_options, code->top_bracket, FALSE, NULL); |
| if (errorcode != 0) goto BADESCAPE; |
|
|
| switch(rc) |
| { |
| case ESC_E: |
| goto SETFORCECASE; |
|
|
| case ESC_Q: |
| escaped_literal = TRUE; |
| continue; |
|
|
| case 0: |
| case ESC_b: |
| case ESC_v: |
|
|
| if (rc == ESC_b) ch = CHAR_BS; |
| if (rc == ESC_v) ch = CHAR_VT; |
|
|
| #ifdef SUPPORT_UNICODE |
| if (utf) chlen = PRIV(ord2utf)(ch, temp); else |
| #endif |
| { |
| temp[0] = ch; |
| chlen = 1; |
| } |
|
|
| if (forcecase.to_case != PCRE2_SUBSTITUTE_CASE_NONE && |
| substitute_case_callout == NULL) |
| CHECKCASECPY_DEFAULT(temp, chlen); |
| else |
| CHECKMEMCPY(temp, chlen); |
| continue; |
|
|
| case ESC_g: |
| { |
| PCRE2_SIZE name_len; |
| PCRE2_SPTR name_start; |
|
|
| |
| if (ptr >= repend || *ptr != CHAR_LESS_THAN_SIGN) |
| goto BADESCAPE; |
| ++ptr; |
|
|
| name_start = ptr; |
| if (!read_name_subst(&ptr, repend, utf, code->tables + ctypes_offset)) |
| goto BADESCAPE; |
| name_len = ptr - name_start; |
|
|
| if (ptr >= repend || *ptr != CHAR_GREATER_THAN_SIGN) |
| goto BADESCAPE; |
| ++ptr; |
|
|
| special = 0; |
| group = -1; |
| memcpy(name, name_start, CU2BYTES(name_len)); |
| name[name_len] = 0; |
| goto GROUP_SUBSTITUTE; |
| } |
|
|
| default: |
| if (rc < 0) |
| { |
| special = 0; |
| group = -rc - 1; |
| goto GROUP_SUBSTITUTE; |
| } |
| goto BADESCAPE; |
| } |
| } |
|
|
| |
|
|
| else |
| { |
| PCRE2_SPTR ch_start; |
|
|
| LOADLITERAL: |
| ch_start = ptr; |
| GETCHARINCTEST(ch, ptr); |
| (void) ch; |
|
|
| if (forcecase.to_case != PCRE2_SUBSTITUTE_CASE_NONE && |
| substitute_case_callout == NULL) |
| CHECKCASECPY_DEFAULT(ch_start, ptr - ch_start); |
| else |
| CHECKMEMCPY(ch_start, ptr - ch_start); |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
|
|
| if (substitute_case_callout != NULL && |
| forcecase.to_case != PCRE2_SUBSTITUTE_CASE_NONE) |
| DELAYEDFORCECASE(); |
|
|
| |
| |
|
|
| if (mcontext != NULL && mcontext->substitute_callout != NULL) |
| { |
| |
|
|
| if (!overflowed) |
| { |
| scb.subscount = subs; |
| scb.output_offsets[1] = buff_offset; |
| rc = mcontext->substitute_callout(&scb, |
| mcontext->substitute_callout_data); |
|
|
| |
| |
|
|
| if (rc != 0) |
| { |
| PCRE2_SIZE newlength = scb.output_offsets[1] - scb.output_offsets[0]; |
| PCRE2_SIZE oldlength = ovector[1] - ovector[0]; |
|
|
| buff_offset -= newlength; |
| lengthleft += newlength; |
| if (!replacement_only) CHECKMEMCPY(subject + ovector[0], oldlength); |
|
|
| |
|
|
| if (rc < 0) suboptions &= (~PCRE2_SUBSTITUTE_GLOBAL); |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| else |
| { |
| PCRE2_SIZE newlength_buf = buff_offset - scb.output_offsets[0]; |
| PCRE2_SIZE newlength_extra = extra_needed - sub_start_extra_needed; |
| PCRE2_SIZE newlength = |
| (newlength_extra > ~(PCRE2_SIZE)0 - newlength_buf)? |
| ~(PCRE2_SIZE)0 : newlength_buf + newlength_extra; |
| PCRE2_SIZE oldlength = ovector[1] - ovector[0]; |
|
|
| |
| |
|
|
| if (oldlength > newlength) |
| { |
| PCRE2_SIZE additional = oldlength - newlength; |
| if (additional > ~(PCRE2_SIZE)0 - extra_needed) |
| goto TOOLARGEREPLACE; |
| extra_needed += additional; |
| } |
|
|
| |
| |
| |
| } |
| } |
|
|
| |
| |
|
|
| if ((suboptions & PCRE2_SUBSTITUTE_GLOBAL) == 0 || |
| !pcre2_next_match(match_data, &start_offset, &goptions)) |
| { |
| start_offset = ovector[1]; |
| break; |
| } |
|
|
| |
| |
| |
| |
| |
|
|
| PCRE2_ASSERT(start_offset == ovector[1]); |
|
|
| } |
|
|
| |
| |
|
|
| if (!replacement_only) |
| { |
| fraglength = length - start_offset; |
| CHECKMEMCPY(subject + start_offset, fraglength); |
| } |
|
|
| temp[0] = 0; |
| CHECKMEMCPY(temp, 1); |
|
|
| |
| |
| |
|
|
| if (overflowed) |
| { |
| rc = PCRE2_ERROR_NOMEMORY; |
|
|
| if (extra_needed > ~(PCRE2_SIZE)0 - buff_length) |
| goto TOOLARGEREPLACE; |
| *blength = buff_length + extra_needed; |
| } |
|
|
| |
| |
|
|
| else |
| { |
| rc = subs; |
| *blength = buff_offset - 1; |
| } |
|
|
| EXIT: |
| if (internal_match_data != NULL) pcre2_match_data_free(internal_match_data); |
| else match_data->rc = rc; |
| return rc; |
|
|
| NOROOM: |
| rc = PCRE2_ERROR_NOMEMORY; |
| goto EXIT; |
|
|
| CASEERROR: |
| rc = PCRE2_ERROR_REPLACECASE; |
| goto EXIT; |
|
|
| TOOLARGEREPLACE: |
| rc = PCRE2_ERROR_TOOLARGEREPLACE; |
| goto EXIT; |
|
|
| BAD: |
| rc = PCRE2_ERROR_BADREPLACEMENT; |
| goto PTREXIT; |
|
|
| BADESCAPE: |
| rc = PCRE2_ERROR_BADREPESCAPE; |
|
|
| PTREXIT: |
| *blength = (PCRE2_SIZE)(ptr - replacement); |
| goto EXIT; |
| } |
|
|
| |
|
|