Revision: 388
http://www.exim.org/viewvc/pcre2?view=rev&revision=388
Author: ph10
Date: 2015-10-17 19:29:01 +0100 (Sat, 17 Oct 2015)
Log Message:
-----------
Fix erroneous "\ at end of pattern" errors, introduced by
PCRE2_SUBSTITUTE_EXTENDED patch.
Modified Paths:
--------------
code/trunk/ChangeLog
code/trunk/src/pcre2_compile.c
code/trunk/src/pcre2_intmodedep.h
code/trunk/src/pcre2_substitute.c
Modified: code/trunk/ChangeLog
===================================================================
--- code/trunk/ChangeLog 2015-10-17 18:27:38 UTC (rev 387)
+++ code/trunk/ChangeLog 2015-10-17 18:29:01 UTC (rev 388)
@@ -203,7 +203,10 @@
58. Implemented --never-backslash-C.
+59. Change 55 above introduced a bug by which certain patterns provoked the
+erroneous error "\ at end of pattern".
+
Version 10.20 30-June-2015
--------------------------
Modified: code/trunk/src/pcre2_compile.c
===================================================================
--- code/trunk/src/pcre2_compile.c 2015-10-17 18:27:38 UTC (rev 387)
+++ code/trunk/src/pcre2_compile.c 2015-10-17 18:29:01 UTC (rev 388)
@@ -1643,9 +1643,10 @@
int escape = 0;
int i;
-/* If backslash is at the end of the pattern, it's an error. */
+/* If backslash is at the end of the string, it's an error. The check must be
+skipped when processing a nested insertion string during compilation. */
-if (ptr >= ptrend)
+if ((cb == NULL || cb->nestptr == NULL) && ptr >= ptrend)
{
*errorcodeptr = ERR1;
return 0;
@@ -3612,7 +3613,6 @@
BOOL groupsetfirstcu = FALSE;
PCRE2_SPTR ptr = *ptrptr;
PCRE2_SPTR tempptr;
-PCRE2_SPTR nestptr = NULL;
PCRE2_UCHAR *previous = NULL;
PCRE2_UCHAR *previous_callout = NULL;
uint8_t classbits[32];
@@ -3700,12 +3700,13 @@
c = *ptr;
/* If we are at the end of a nested substitution, revert to the outer level
- string. Nesting only happens one level deep. */
+ string. Nesting only happens one level deep, and the inserted string is
+ always zero terminated. */
- if (c == CHAR_NULL && nestptr != NULL)
+ if (c == CHAR_NULL && cb->nestptr != NULL)
{
- ptr = nestptr;
- nestptr = NULL;
+ ptr = cb->nestptr;
+ cb->nestptr = NULL;
c = *ptr;
}
@@ -3822,7 +3823,7 @@
/* Fill in length of a previous callout, except when the next thing is a
quantifier or when processing a property substitution string in UCP mode. */
- if (!is_quantifier && previous_callout != NULL && nestptr == NULL &&
+ if (!is_quantifier && previous_callout != NULL && cb->nestptr == NULL &&
after_manual_callout-- <= 0)
{
if (lengthptr == NULL) /* Don't attempt in pre-compile phase */
@@ -3833,7 +3834,7 @@
/* Create auto callout, except for quantifiers, or while processing property
strings that are substituted for \w etc in UCP mode. */
- if ((options & PCRE2_AUTO_CALLOUT) != 0 && !is_quantifier && nestptr == NULL)
+ if ((options & PCRE2_AUTO_CALLOUT) != 0 && !is_quantifier && cb->nestptr == NULL)
{
previous_callout = code;
code = auto_callout(code, ptr, cb);
@@ -3931,7 +3932,7 @@
case CHAR_LEFT_SQUARE_BRACKET:
if (PRIV(strncmp_c8)(ptr+1, STRING_WEIRD_STARTWORD, 6) == 0)
{
- nestptr = ptr + 7;
+ cb->nestptr = ptr + 7;
ptr = sub_start_of_word; /* Do not combine these statements; clang's */
ptr--; /* sanitizer moans about a negative index. */
continue;
@@ -3939,7 +3940,7 @@
if (PRIV(strncmp_c8)(ptr+1, STRING_WEIRD_ENDWORD, 6) == 0)
{
- nestptr = ptr + 7;
+ cb->nestptr = ptr + 7;
ptr = sub_end_of_word; /* Do not combine these statements; clang's */
ptr--; /* sanitizer moans about a negative index. */
continue;
@@ -4128,7 +4129,7 @@
if (posix_substitutes[pc] != NULL)
{
- nestptr = tempptr + 1;
+ cb->nestptr = tempptr + 1;
ptr = posix_substitutes[pc] - 1;
goto CONTINUE_CLASS;
}
@@ -4264,7 +4265,7 @@
case ESC_WU: /* or \P to test Unicode properties instead */
case ESC_su: /* of the default ASCII testing. */
case ESC_SU:
- nestptr = ptr;
+ cb->nestptr = ptr;
ptr = substitutes[escape - ESC_DU] - 1; /* Just before substitute */
class_has_8bitchar--; /* Undo! */
break;
@@ -4606,10 +4607,10 @@
CONTINUE_CLASS:
c = *(++ptr);
- if (c == 0 && nestptr != NULL)
+ if (c == 0 && cb->nestptr != NULL)
{
- ptr = nestptr;
- nestptr = NULL;
+ ptr = cb->nestptr;
+ cb->nestptr = NULL;
c = *(++ptr);
}
@@ -7081,7 +7082,7 @@
#ifdef SUPPORT_UNICODE
if (escape >= ESC_DU && escape <= ESC_wu)
{
- nestptr = ptr + 1; /* Where to resume */
+ cb->nestptr = ptr + 1; /* Where to resume */
ptr = substitutes[escape - ESC_DU] - 1; /* Just before substitute */
}
else
@@ -8078,6 +8079,7 @@
cb.cx = ccontext;
cb.dupnames = FALSE;
cb.end_pattern = pattern + patlen;
+cb.nestptr = NULL;
cb.external_flags = 0;
cb.external_options = options;
cb.had_recurse = FALSE;
Modified: code/trunk/src/pcre2_intmodedep.h
===================================================================
--- code/trunk/src/pcre2_intmodedep.h 2015-10-17 18:27:38 UTC (rev 387)
+++ code/trunk/src/pcre2_intmodedep.h 2015-10-17 18:29:01 UTC (rev 388)
@@ -686,6 +686,7 @@
PCRE2_SPTR start_code; /* The start of the compiled code */
PCRE2_SPTR start_pattern; /* The start of the pattern */
PCRE2_SPTR end_pattern; /* The end of the pattern */
+ PCRE2_SPTR nestptr; /* Pointer saved for string substitution */
PCRE2_UCHAR *name_table; /* The name/number table */
size_t workspace_size; /* Size of workspace */
uint16_t names_found; /* Number of entries so far */
Modified: code/trunk/src/pcre2_substitute.c
===================================================================
--- code/trunk/src/pcre2_substitute.c 2015-10-17 18:27:38 UTC (rev 387)
+++ code/trunk/src/pcre2_substitute.c 2015-10-17 18:29:01 UTC (rev 388)
@@ -197,7 +197,9 @@
BOOL global = FALSE;
BOOL extended = FALSE;
BOOL literal = FALSE;
+#ifdef SUPPORT_UNICODE
BOOL utf = (code->overall_options & PCRE2_UTF) != 0;
+#endif
PCRE2_SPTR ptr;
PCRE2_SPTR repend;
PCRE2_SIZE buff_offset, buff_length, lengthleft, fraglength;