chiark / gitweb /
pcre3 (2:8.38-1) unstable; urgency=low
[pcre3.git] / debian / patches / Fix-bad-compile-for-groups-like-2-0-1999.patch
1 Description: CVE-2015-2325: heap buffer overflow in compile_branch()
2  Fix bad compile for groups like "((?2){0,1999}())?".
3 Origin: backport, http://vcs.pcre.org/pcre?view=revision&revision=1528
4 Bug: http://bugs.exim.org/show_bug.cgi?id=1591
5 Bug-Debian: https://bugs.debian.org/781795
6 Forwarded: not-needed
7 Last-Update: 2015-09-10
8 Applied-Upstream: 8.37
9
10 --- a/pcre_compile.c
11 +++ b/pcre_compile.c
12 @@ -3933,14 +3933,14 @@ Arguments:
13    adjust     the amount by which the group is to be moved
14    utf        TRUE in UTF-8 / UTF-16 / UTF-32 mode
15    cd         contains pointers to tables etc.
16 -  save_hwm   the hwm forward reference pointer at the start of the group
17 +  save_hwm_offset   the hwm forward reference offset at the start of the group
18  
19  Returns:     nothing
20  */
21  
22  static void
23  adjust_recurse(pcre_uchar *group, int adjust, BOOL utf, compile_data *cd,
24 -  pcre_uchar *save_hwm)
25 +  size_t save_hwm_offset)
26  {
27  pcre_uchar *ptr = group;
28  
29 @@ -3952,7 +3952,8 @@ while ((ptr = (pcre_uchar *)find_recurse
30    /* See if this recursion is on the forward reference list. If so, adjust the
31    reference. */
32  
33 -  for (hc = save_hwm; hc < cd->hwm; hc += LINK_SIZE)
34 +  for (hc = (pcre_uchar *)cd->start_workspace + save_hwm_offset; hc < cd->hwm; 
35 +       hc += LINK_SIZE)
36      {
37      offset = (int)GET(hc, 0);
38      if (cd->start_code + offset == ptr + 1)
39 @@ -4397,7 +4398,7 @@ const pcre_uchar *tempptr;
40  const pcre_uchar *nestptr = NULL;
41  pcre_uchar *previous = NULL;
42  pcre_uchar *previous_callout = NULL;
43 -pcre_uchar *save_hwm = NULL;
44 +size_t save_hwm_offset = 0;
45  pcre_uint8 classbits[32];
46  
47  /* We can fish out the UTF-8 setting once and for all into a BOOL, but we
48 @@ -5909,7 +5910,7 @@ for (;; ptr++)
49          if (repeat_max <= 1)    /* Covers 0, 1, and unlimited */
50            {
51            *code = OP_END;
52 -          adjust_recurse(previous, 1, utf, cd, save_hwm);
53 +          adjust_recurse(previous, 1, utf, cd, save_hwm_offset);
54            memmove(previous + 1, previous, IN_UCHARS(len));
55            code++;
56            if (repeat_max == 0)
57 @@ -5933,7 +5934,7 @@ for (;; ptr++)
58            {
59            int offset;
60            *code = OP_END;
61 -          adjust_recurse(previous, 2 + LINK_SIZE, utf, cd, save_hwm);
62 +          adjust_recurse(previous, 2 + LINK_SIZE, utf, cd, save_hwm_offset);
63            memmove(previous + 2 + LINK_SIZE, previous, IN_UCHARS(len));
64            code += 2 + LINK_SIZE;
65            *previous++ = OP_BRAZERO + repeat_type;
66 @@ -5996,26 +5997,25 @@ for (;; ptr++)
67              for (i = 1; i < repeat_min; i++)
68                {
69                pcre_uchar *hc;
70 -              pcre_uchar *this_hwm = cd->hwm;
71 +              size_t this_hwm_offset = cd->hwm - cd->start_workspace;
72                memcpy(code, previous, IN_UCHARS(len));
73  
74                while (cd->hwm > cd->start_workspace + cd->workspace_size -
75 -                     WORK_SIZE_SAFETY_MARGIN - (this_hwm - save_hwm))
76 +                     WORK_SIZE_SAFETY_MARGIN -
77 +                     (this_hwm_offset - save_hwm_offset))
78                  {
79 -                int save_offset = save_hwm - cd->start_workspace;
80 -                int this_offset = this_hwm - cd->start_workspace;
81                  *errorcodeptr = expand_workspace(cd);
82                  if (*errorcodeptr != 0) goto FAILED;
83 -                save_hwm = (pcre_uchar *)cd->start_workspace + save_offset;
84 -                this_hwm = (pcre_uchar *)cd->start_workspace + this_offset;
85                  }
86  
87 -              for (hc = save_hwm; hc < this_hwm; hc += LINK_SIZE)
88 +              for (hc = (pcre_uchar *)cd->start_workspace + save_hwm_offset;
89 +                   hc < (pcre_uchar *)cd->start_workspace + this_hwm_offset;
90 +                   hc += LINK_SIZE)
91                  {
92                  PUT(cd->hwm, 0, GET(hc, 0) + len);
93                  cd->hwm += LINK_SIZE;
94                  }
95 -              save_hwm = this_hwm;
96 +              save_hwm_offset = this_hwm_offset;
97                code += len;
98                }
99              }
100 @@ -6060,7 +6060,7 @@ for (;; ptr++)
101          else for (i = repeat_max - 1; i >= 0; i--)
102            {
103            pcre_uchar *hc;
104 -          pcre_uchar *this_hwm = cd->hwm;
105 +          size_t this_hwm_offset = cd->hwm - cd->start_workspace;
106  
107            *code++ = OP_BRAZERO + repeat_type;
108  
109 @@ -6082,22 +6082,21 @@ for (;; ptr++)
110            copying them. */
111  
112            while (cd->hwm > cd->start_workspace + cd->workspace_size -
113 -                 WORK_SIZE_SAFETY_MARGIN - (this_hwm - save_hwm))
114 +                 WORK_SIZE_SAFETY_MARGIN -
115 +                 (this_hwm_offset - save_hwm_offset))
116              {
117 -            int save_offset = save_hwm - cd->start_workspace;
118 -            int this_offset = this_hwm - cd->start_workspace;
119              *errorcodeptr = expand_workspace(cd);
120              if (*errorcodeptr != 0) goto FAILED;
121 -            save_hwm = (pcre_uchar *)cd->start_workspace + save_offset;
122 -            this_hwm = (pcre_uchar *)cd->start_workspace + this_offset;
123              }
124  
125 -          for (hc = save_hwm; hc < this_hwm; hc += LINK_SIZE)
126 +          for (hc = (pcre_uchar *)cd->start_workspace + save_hwm_offset;
127 +               hc < (pcre_uchar *)cd->start_workspace + this_hwm_offset;
128 +               hc += LINK_SIZE)
129              {
130              PUT(cd->hwm, 0, GET(hc, 0) + len + ((i != 0)? 2+LINK_SIZE : 1));
131              cd->hwm += LINK_SIZE;
132              }
133 -          save_hwm = this_hwm;
134 +          save_hwm_offset = this_hwm_offset;
135            code += len;
136            }
137  
138 @@ -6193,7 +6192,7 @@ for (;; ptr++)
139                {
140                int nlen = (int)(code - bracode);
141                *code = OP_END;
142 -              adjust_recurse(bracode, 1 + LINK_SIZE, utf, cd, save_hwm);
143 +              adjust_recurse(bracode, 1 + LINK_SIZE, utf, cd, save_hwm_offset);
144                memmove(bracode + 1 + LINK_SIZE, bracode, IN_UCHARS(nlen));
145                code += 1 + LINK_SIZE;
146                nlen += 1 + LINK_SIZE;
147 @@ -6327,7 +6326,7 @@ for (;; ptr++)
148          else
149            {
150            *code = OP_END;
151 -          adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, save_hwm);
152 +          adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, save_hwm_offset);
153            memmove(tempcode + 1 + LINK_SIZE, tempcode, IN_UCHARS(len));
154            code += 1 + LINK_SIZE;
155            len += 1 + LINK_SIZE;
156 @@ -6376,7 +6375,7 @@ for (;; ptr++)
157  
158          default:
159          *code = OP_END;
160 -        adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, save_hwm);
161 +        adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, save_hwm_offset);
162          memmove(tempcode + 1 + LINK_SIZE, tempcode, IN_UCHARS(len));
163          code += 1 + LINK_SIZE;
164          len += 1 + LINK_SIZE;
165 @@ -6408,7 +6407,7 @@ for (;; ptr++)
166      newoptions = options;
167      skipbytes = 0;
168      bravalue = OP_CBRA;
169 -    save_hwm = cd->hwm;
170 +    save_hwm_offset = cd->hwm - cd->start_workspace;
171      reset_bracount = FALSE;
172  
173      /* First deal with various "verbs" that can be introduced by '*'. */
174 @@ -7701,7 +7700,7 @@ for (;; ptr++)
175          const pcre_uchar *p;
176          pcre_uint32 cf;
177  
178 -        save_hwm = cd->hwm;   /* Normally this is set when '(' is read */
179 +        save_hwm_offset = cd->hwm - cd->start_workspace;   /* Normally this is set when '(' is read */
180          terminator = (*(++ptr) == CHAR_LESS_THAN_SIGN)?
181            CHAR_GREATER_THAN_SIGN : CHAR_APOSTROPHE;
182  
183 @@ -8247,7 +8246,7 @@ for (;;)
184          {
185          *code = OP_END;
186          adjust_recurse(start_bracket, 1 + LINK_SIZE,
187 -          (options & PCRE_UTF8) != 0, cd, cd->hwm);
188 +          (options & PCRE_UTF8) != 0, cd, cd->hwm - cd->start_workspace);
189          memmove(start_bracket + 1 + LINK_SIZE, start_bracket,
190            IN_UCHARS(code - start_bracket));
191          *start_bracket = OP_ONCE;
192 --- a/testdata/testinput2
193 +++ b/testdata/testinput2
194 @@ -4064,4 +4064,6 @@ backtracking verbs. --/
195  
196  /(((((a)))))/Q
197  
198 +"((?2){0,1999}())?"
199 +
200  /-- End of testinput2 --/
201 --- a/testdata/testoutput2
202 +++ b/testdata/testoutput2
203 @@ -14173,4 +14173,6 @@ Failed: parentheses are too deeply neste
204  /(((((a)))))/Q
205  ** Missing 0 or 1 after /Q
206  
207 +"((?2){0,1999}())?"
208 +
209  /-- End of testinput2 --/