Commit | Line | Data |
---|---|---|
13bea701 VM |
1 | commit 7af8e8717def179fd7b69e173abd347c1a3547cb |
2 | Author: ph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15> | |
3 | Date: Wed Aug 5 15:38:32 2015 +0000 | |
4 | ||
5 | Fix buffer overflow for named references in (?| situations. | |
6 | ||
7 | ||
8 | git-svn-id: svn://vcs.exim.org/pcre/code/trunk@1585 2f5784b3-3f2a-0410-8824-cb99058d5e15 | |
9 | ||
10 | diff --git a/pcre_compile.c b/pcre_compile.c | |
11 | index 7d9f276..89ca8f1 100644 | |
12 | --- a/pcre_compile.c | |
13 | +++ b/pcre_compile.c | |
14 | @@ -6668,6 +6668,7 @@ for (;; ptr++) | |
15 | /* ------------------------------------------------------------ */ | |
16 | case CHAR_VERTICAL_LINE: /* Reset capture count for each branch */ | |
17 | reset_bracount = TRUE; | |
18 | + cd->dupgroups = TRUE; /* Record (?| encountered */ | |
19 | /* Fall through */ | |
20 | ||
21 | /* ------------------------------------------------------------ */ | |
22 | @@ -7178,7 +7179,8 @@ for (;; ptr++) | |
23 | if (lengthptr != NULL) | |
24 | { | |
25 | named_group *ng; | |
26 | - | |
27 | + recno = 0; | |
28 | + | |
29 | if (namelen == 0) | |
30 | { | |
31 | *errorcodeptr = ERR62; | |
32 | @@ -7195,32 +7197,6 @@ for (;; ptr++) | |
33 | goto FAILED; | |
34 | } | |
35 | ||
36 | - /* The name table does not exist in the first pass; instead we must | |
37 | - scan the list of names encountered so far in order to get the | |
38 | - number. If the name is not found, set the value to 0 for a forward | |
39 | - reference. */ | |
40 | - | |
41 | - recno = 0; | |
42 | - ng = cd->named_groups; | |
43 | - for (i = 0; i < cd->names_found; i++, ng++) | |
44 | - { | |
45 | - if (namelen == ng->length && | |
46 | - STRNCMP_UC_UC(name, ng->name, namelen) == 0) | |
47 | - { | |
48 | - open_capitem *oc; | |
49 | - recno = ng->number; | |
50 | - if (is_recurse) break; | |
51 | - for (oc = cd->open_caps; oc != NULL; oc = oc->next) | |
52 | - { | |
53 | - if (oc->number == recno) | |
54 | - { | |
55 | - oc->flag = TRUE; | |
56 | - break; | |
57 | - } | |
58 | - } | |
59 | - } | |
60 | - } | |
61 | - | |
62 | /* Count named back references. */ | |
63 | ||
64 | if (!is_recurse) cd->namedrefcount++; | |
65 | @@ -7242,7 +7218,44 @@ for (;; ptr++) | |
66 | issue is fixed "properly" in PCRE2. As PCRE1 is now in maintenance | |
67 | only mode, we finesse the bug by allowing more memory always. */ | |
68 | ||
69 | - /* if (recno == 0) */ *lengthptr += 2 + 2*LINK_SIZE; | |
70 | + *lengthptr += 2 + 2*LINK_SIZE; | |
71 | + | |
72 | + /* It is even worse than that. The current reference may be to an | |
73 | + existing named group with a different number (so apparently not | |
74 | + recursive) but which later on is also attached to a group with the | |
75 | + current number. This can only happen if $(| has been previous | |
76 | + encountered. In that case, we allow yet more memory, just in case. | |
77 | + (Again, this is fixed "properly" in PCRE2. */ | |
78 | + | |
79 | + if (cd->dupgroups) *lengthptr += 2 + 2*LINK_SIZE; | |
80 | + | |
81 | + /* Otherwise, check for recursion here. The name table does not exist | |
82 | + in the first pass; instead we must scan the list of names encountered | |
83 | + so far in order to get the number. If the name is not found, leave | |
84 | + the value of recno as 0 for a forward reference. */ | |
85 | + | |
86 | + else | |
87 | + { | |
88 | + ng = cd->named_groups; | |
89 | + for (i = 0; i < cd->names_found; i++, ng++) | |
90 | + { | |
91 | + if (namelen == ng->length && | |
92 | + STRNCMP_UC_UC(name, ng->name, namelen) == 0) | |
93 | + { | |
94 | + open_capitem *oc; | |
95 | + recno = ng->number; | |
96 | + if (is_recurse) break; | |
97 | + for (oc = cd->open_caps; oc != NULL; oc = oc->next) | |
98 | + { | |
99 | + if (oc->number == recno) | |
100 | + { | |
101 | + oc->flag = TRUE; | |
102 | + break; | |
103 | + } | |
104 | + } | |
105 | + } | |
106 | + } | |
107 | + } | |
108 | } | |
109 | ||
110 | /* In the real compile, search the name table. We check the name | |
111 | @@ -7289,8 +7302,6 @@ for (;; ptr++) | |
112 | for (i++; i < cd->names_found; i++) | |
113 | { | |
114 | if (STRCMP_UC_UC(slot + IMM2_SIZE, cslot + IMM2_SIZE) != 0) break; | |
115 | - | |
116 | - | |
117 | count++; | |
118 | cslot += cd->name_entry_size; | |
119 | } | |
120 | @@ -9239,6 +9250,7 @@ cd->names_found = 0; | |
121 | cd->name_entry_size = 0; | |
122 | cd->name_table = NULL; | |
123 | cd->dupnames = FALSE; | |
124 | +cd->dupgroups = FALSE; | |
125 | cd->namedrefcount = 0; | |
126 | cd->start_code = cworkspace; | |
127 | cd->hwm = cworkspace; | |
128 | @@ -9273,7 +9285,7 @@ if (errorcode != 0) goto PCRE_EARLY_ERROR_RETURN; | |
129 | ||
130 | DPRINTF(("end pre-compile: length=%d workspace=%d\n", length, | |
131 | (int)(cd->hwm - cworkspace))); | |
132 | - | |
133 | + | |
134 | if (length > MAX_PATTERN_SIZE) | |
135 | { | |
136 | errorcode = ERR20; | |
137 | diff --git a/pcre_internal.h b/pcre_internal.h | |
138 | index 80e2420..544d9c0 100644 | |
139 | --- a/pcre_internal.h | |
140 | +++ b/pcre_internal.h | |
141 | @@ -2454,6 +2454,7 @@ typedef struct compile_data { | |
142 | BOOL had_pruneorskip; /* (*PRUNE) or (*SKIP) encountered */ | |
143 | BOOL check_lookbehind; /* Lookbehinds need later checking */ | |
144 | BOOL dupnames; /* Duplicate names exist */ | |
145 | + BOOL dupgroups; /* Duplicate groups exist: (?| found */ | |
146 | BOOL iscondassert; /* Next assert is a condition */ | |
147 | int nltype; /* Newline type */ | |
148 | int nllen; /* Newline string length */ | |
149 | diff --git a/testdata/testinput2 b/testdata/testinput2 | |
150 | index df2c1cc..e119bd9 100644 | |
151 | --- a/testdata/testinput2 | |
152 | +++ b/testdata/testinput2 | |
153 | @@ -4194,4 +4194,6 @@ backtracking verbs. --/ | |
154 | ||
155 | /(?1){3918}(((((0(\k'R'))))(?J)(?'R'(?'R'\3){99})))/I | |
156 | ||
157 | +/(?J:(?|(:(?|(?'R')(\k'R')|((?'R')))H'Rk'Rf)|s(?'R')))/ | |
158 | + | |
159 | /-- End of testinput2 --/ | |
160 | diff --git a/testdata/testoutput2 b/testdata/testoutput2 | |
161 | index d3fc254..54db2cc 100644 | |
162 | --- a/testdata/testoutput2 | |
163 | +++ b/testdata/testoutput2 | |
164 | @@ -14537,4 +14537,6 @@ Duplicate name status changes | |
165 | No first char | |
166 | Need char = '0' | |
167 | ||
168 | +/(?J:(?|(:(?|(?'R')(\k'R')|((?'R')))H'Rk'Rf)|s(?'R')))/ | |
169 | + | |
170 | /-- End of testinput2 --/ |