171 lines
5.9 KiB
Diff
171 lines
5.9 KiB
Diff
commit 7af8e8717def179fd7b69e173abd347c1a3547cb
|
|
Author: ph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15>
|
|
Date: Wed Aug 5 15:38:32 2015 +0000
|
|
|
|
Fix buffer overflow for named references in (?| situations.
|
|
|
|
|
|
git-svn-id: svn://vcs.exim.org/pcre/code/trunk@1585 2f5784b3-3f2a-0410-8824-cb99058d5e15
|
|
|
|
diff --git a/pcre_compile.c b/pcre_compile.c
|
|
index 7d9f276..89ca8f1 100644
|
|
--- a/pcre_compile.c
|
|
+++ b/pcre_compile.c
|
|
@@ -6668,6 +6668,7 @@ for (;; ptr++)
|
|
/* ------------------------------------------------------------ */
|
|
case CHAR_VERTICAL_LINE: /* Reset capture count for each branch */
|
|
reset_bracount = TRUE;
|
|
+ cd->dupgroups = TRUE; /* Record (?| encountered */
|
|
/* Fall through */
|
|
|
|
/* ------------------------------------------------------------ */
|
|
@@ -7178,7 +7179,8 @@ for (;; ptr++)
|
|
if (lengthptr != NULL)
|
|
{
|
|
named_group *ng;
|
|
-
|
|
+ recno = 0;
|
|
+
|
|
if (namelen == 0)
|
|
{
|
|
*errorcodeptr = ERR62;
|
|
@@ -7195,32 +7197,6 @@ for (;; ptr++)
|
|
goto FAILED;
|
|
}
|
|
|
|
- /* The name table does not exist in the first pass; instead we must
|
|
- scan the list of names encountered so far in order to get the
|
|
- number. If the name is not found, set the value to 0 for a forward
|
|
- reference. */
|
|
-
|
|
- recno = 0;
|
|
- ng = cd->named_groups;
|
|
- for (i = 0; i < cd->names_found; i++, ng++)
|
|
- {
|
|
- if (namelen == ng->length &&
|
|
- STRNCMP_UC_UC(name, ng->name, namelen) == 0)
|
|
- {
|
|
- open_capitem *oc;
|
|
- recno = ng->number;
|
|
- if (is_recurse) break;
|
|
- for (oc = cd->open_caps; oc != NULL; oc = oc->next)
|
|
- {
|
|
- if (oc->number == recno)
|
|
- {
|
|
- oc->flag = TRUE;
|
|
- break;
|
|
- }
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
/* Count named back references. */
|
|
|
|
if (!is_recurse) cd->namedrefcount++;
|
|
@@ -7242,7 +7218,44 @@ for (;; ptr++)
|
|
issue is fixed "properly" in PCRE2. As PCRE1 is now in maintenance
|
|
only mode, we finesse the bug by allowing more memory always. */
|
|
|
|
- /* if (recno == 0) */ *lengthptr += 2 + 2*LINK_SIZE;
|
|
+ *lengthptr += 2 + 2*LINK_SIZE;
|
|
+
|
|
+ /* It is even worse than that. The current reference may be to an
|
|
+ existing named group with a different number (so apparently not
|
|
+ recursive) but which later on is also attached to a group with the
|
|
+ current number. This can only happen if $(| has been previous
|
|
+ encountered. In that case, we allow yet more memory, just in case.
|
|
+ (Again, this is fixed "properly" in PCRE2. */
|
|
+
|
|
+ if (cd->dupgroups) *lengthptr += 2 + 2*LINK_SIZE;
|
|
+
|
|
+ /* Otherwise, check for recursion here. The name table does not exist
|
|
+ in the first pass; instead we must scan the list of names encountered
|
|
+ so far in order to get the number. If the name is not found, leave
|
|
+ the value of recno as 0 for a forward reference. */
|
|
+
|
|
+ else
|
|
+ {
|
|
+ ng = cd->named_groups;
|
|
+ for (i = 0; i < cd->names_found; i++, ng++)
|
|
+ {
|
|
+ if (namelen == ng->length &&
|
|
+ STRNCMP_UC_UC(name, ng->name, namelen) == 0)
|
|
+ {
|
|
+ open_capitem *oc;
|
|
+ recno = ng->number;
|
|
+ if (is_recurse) break;
|
|
+ for (oc = cd->open_caps; oc != NULL; oc = oc->next)
|
|
+ {
|
|
+ if (oc->number == recno)
|
|
+ {
|
|
+ oc->flag = TRUE;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
/* In the real compile, search the name table. We check the name
|
|
@@ -7289,8 +7302,6 @@ for (;; ptr++)
|
|
for (i++; i < cd->names_found; i++)
|
|
{
|
|
if (STRCMP_UC_UC(slot + IMM2_SIZE, cslot + IMM2_SIZE) != 0) break;
|
|
-
|
|
-
|
|
count++;
|
|
cslot += cd->name_entry_size;
|
|
}
|
|
@@ -9239,6 +9250,7 @@ cd->names_found = 0;
|
|
cd->name_entry_size = 0;
|
|
cd->name_table = NULL;
|
|
cd->dupnames = FALSE;
|
|
+cd->dupgroups = FALSE;
|
|
cd->namedrefcount = 0;
|
|
cd->start_code = cworkspace;
|
|
cd->hwm = cworkspace;
|
|
@@ -9273,7 +9285,7 @@ if (errorcode != 0) goto PCRE_EARLY_ERROR_RETURN;
|
|
|
|
DPRINTF(("end pre-compile: length=%d workspace=%d\n", length,
|
|
(int)(cd->hwm - cworkspace)));
|
|
-
|
|
+
|
|
if (length > MAX_PATTERN_SIZE)
|
|
{
|
|
errorcode = ERR20;
|
|
diff --git a/pcre_internal.h b/pcre_internal.h
|
|
index 80e2420..544d9c0 100644
|
|
--- a/pcre_internal.h
|
|
+++ b/pcre_internal.h
|
|
@@ -2454,6 +2454,7 @@ typedef struct compile_data {
|
|
BOOL had_pruneorskip; /* (*PRUNE) or (*SKIP) encountered */
|
|
BOOL check_lookbehind; /* Lookbehinds need later checking */
|
|
BOOL dupnames; /* Duplicate names exist */
|
|
+ BOOL dupgroups; /* Duplicate groups exist: (?| found */
|
|
BOOL iscondassert; /* Next assert is a condition */
|
|
int nltype; /* Newline type */
|
|
int nllen; /* Newline string length */
|
|
diff --git a/testdata/testinput2 b/testdata/testinput2
|
|
index df2c1cc..e119bd9 100644
|
|
--- a/testdata/testinput2
|
|
+++ b/testdata/testinput2
|
|
@@ -4194,4 +4194,6 @@ backtracking verbs. --/
|
|
|
|
/(?1){3918}(((((0(\k'R'))))(?J)(?'R'(?'R'\3){99})))/I
|
|
|
|
+/(?J:(?|(:(?|(?'R')(\k'R')|((?'R')))H'Rk'Rf)|s(?'R')))/
|
|
+
|
|
/-- End of testinput2 --/
|
|
diff --git a/testdata/testoutput2 b/testdata/testoutput2
|
|
index d3fc254..54db2cc 100644
|
|
--- a/testdata/testoutput2
|
|
+++ b/testdata/testoutput2
|
|
@@ -14537,4 +14537,6 @@ Duplicate name status changes
|
|
No first char
|
|
Need char = '0'
|
|
|
|
+/(?J:(?|(:(?|(?'R')(\k'R')|((?'R')))H'Rk'Rf)|s(?'R')))/
|
|
+
|
|
/-- End of testinput2 --/
|