chiark / gitweb /
Reapply patches
[pcre3.git] / pcre_byte_order.c
1 /*************************************************
2 *      Perl-Compatible Regular Expressions       *
3 *************************************************/
4
5 /* PCRE is a library of functions to support regular expressions whose syntax
6 and semantics are as close as possible to those of the Perl 5 language.
7
8                        Written by Philip Hazel
9            Copyright (c) 1997-2014 University of Cambridge
10
11 -----------------------------------------------------------------------------
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions are met:
14
15     * Redistributions of source code must retain the above copyright notice,
16       this list of conditions and the following disclaimer.
17
18     * Redistributions in binary form must reproduce the above copyright
19       notice, this list of conditions and the following disclaimer in the
20       documentation and/or other materials provided with the distribution.
21
22     * Neither the name of the University of Cambridge nor the names of its
23       contributors may be used to endorse or promote products derived from
24       this software without specific prior written permission.
25
26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
30 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 POSSIBILITY OF SUCH DAMAGE.
37 -----------------------------------------------------------------------------
38 */
39
40
41 /* This module contains an internal function that tests a compiled pattern to
42 see if it was compiled with the opposite endianness. If so, it uses an
43 auxiliary local function to flip the appropriate bytes. */
44
45
46 #ifdef HAVE_CONFIG_H
47 #include "config.h"
48 #endif
49
50 #include "pcre_internal.h"
51
52
53 /*************************************************
54 *             Swap byte functions                *
55 *************************************************/
56
57 /* The following functions swap the bytes of a pcre_uint16
58 and pcre_uint32 value.
59
60 Arguments:
61   value        any number
62
63 Returns:       the byte swapped value
64 */
65
66 static pcre_uint32
67 swap_uint32(pcre_uint32 value)
68 {
69 return ((value & 0x000000ff) << 24) |
70        ((value & 0x0000ff00) <<  8) |
71        ((value & 0x00ff0000) >>  8) |
72        (value >> 24);
73 }
74
75 static pcre_uint16
76 swap_uint16(pcre_uint16 value)
77 {
78 return (value >> 8) | (value << 8);
79 }
80
81
82 /*************************************************
83 *       Test for a byte-flipped compiled regex   *
84 *************************************************/
85
86 /* This function swaps the bytes of a compiled pattern usually
87 loaded form the disk. It also sets the tables pointer, which
88 is likely an invalid pointer after reload.
89
90 Arguments:
91   argument_re     points to the compiled expression
92   extra_data      points to extra data or is NULL
93   tables          points to the character tables or NULL
94
95 Returns:          0 if the swap is successful, negative on error
96 */
97
98 #if defined COMPILE_PCRE8
99 PCRE_EXP_DECL int pcre_pattern_to_host_byte_order(pcre *argument_re,
100   pcre_extra *extra_data, const unsigned char *tables)
101 #elif defined COMPILE_PCRE16
102 PCRE_EXP_DECL int pcre16_pattern_to_host_byte_order(pcre16 *argument_re,
103   pcre16_extra *extra_data, const unsigned char *tables)
104 #elif defined COMPILE_PCRE32
105 PCRE_EXP_DECL int pcre32_pattern_to_host_byte_order(pcre32 *argument_re,
106   pcre32_extra *extra_data, const unsigned char *tables)
107 #endif
108 {
109 REAL_PCRE *re = (REAL_PCRE *)argument_re;
110 pcre_study_data *study;
111 #ifndef COMPILE_PCRE8
112 pcre_uchar *ptr;
113 int length;
114 #if defined SUPPORT_UTF && defined COMPILE_PCRE16
115 BOOL utf;
116 BOOL utf16_char;
117 #endif /* SUPPORT_UTF && COMPILE_PCRE16 */
118 #endif /* !COMPILE_PCRE8 */
119
120 if (re == NULL) return PCRE_ERROR_NULL;
121 if (re->magic_number == MAGIC_NUMBER)
122   {
123   if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE;
124   re->tables = tables;
125   return 0;
126   }
127
128 if (re->magic_number != REVERSED_MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC;
129 if ((swap_uint32(re->flags) & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE;
130
131 re->magic_number = MAGIC_NUMBER;
132 re->size = swap_uint32(re->size);
133 re->options = swap_uint32(re->options);
134 re->flags = swap_uint32(re->flags);
135 re->limit_match = swap_uint32(re->limit_match);
136 re->limit_recursion = swap_uint32(re->limit_recursion);
137
138 #if defined COMPILE_PCRE8 || defined COMPILE_PCRE16
139 re->first_char = swap_uint16(re->first_char);
140 re->req_char = swap_uint16(re->req_char);
141 #elif defined COMPILE_PCRE32
142 re->first_char = swap_uint32(re->first_char);
143 re->req_char = swap_uint32(re->req_char);
144 #endif
145
146 re->max_lookbehind = swap_uint16(re->max_lookbehind);
147 re->top_bracket = swap_uint16(re->top_bracket);
148 re->top_backref = swap_uint16(re->top_backref);
149 re->name_table_offset = swap_uint16(re->name_table_offset);
150 re->name_entry_size = swap_uint16(re->name_entry_size);
151 re->name_count = swap_uint16(re->name_count);
152 re->ref_count = swap_uint16(re->ref_count);
153 re->tables = tables;
154
155 if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_STUDY_DATA) != 0)
156   {
157   study = (pcre_study_data *)extra_data->study_data;
158   study->size = swap_uint32(study->size);
159   study->flags = swap_uint32(study->flags);
160   study->minlength = swap_uint32(study->minlength);
161   }
162
163 #ifndef COMPILE_PCRE8
164 ptr = (pcre_uchar *)re + re->name_table_offset;
165 length = re->name_count * re->name_entry_size;
166 #if defined SUPPORT_UTF && defined COMPILE_PCRE16
167 utf = (re->options & PCRE_UTF16) != 0;
168 utf16_char = FALSE;
169 #endif /* SUPPORT_UTF && COMPILE_PCRE16 */
170
171 while(TRUE)
172   {
173   /* Swap previous characters. */
174   while (length-- > 0)
175     {
176 #if defined COMPILE_PCRE16
177     *ptr = swap_uint16(*ptr);
178 #elif defined COMPILE_PCRE32
179     *ptr = swap_uint32(*ptr);
180 #endif
181     ptr++;
182     }
183 #if defined SUPPORT_UTF && defined COMPILE_PCRE16
184   if (utf16_char)
185     {
186     if (HAS_EXTRALEN(ptr[-1]))
187       {
188       /* We know that there is only one extra character in UTF-16. */
189       *ptr = swap_uint16(*ptr);
190       ptr++;
191       }
192     }
193   utf16_char = FALSE;
194 #endif /* SUPPORT_UTF */
195
196   /* Get next opcode. */
197   length = 0;
198 #if defined COMPILE_PCRE16
199   *ptr = swap_uint16(*ptr);
200 #elif defined COMPILE_PCRE32
201   *ptr = swap_uint32(*ptr);
202 #endif
203   switch (*ptr)
204     {
205     case OP_END:
206     return 0;
207
208 #if defined SUPPORT_UTF && defined COMPILE_PCRE16
209     case OP_CHAR:
210     case OP_CHARI:
211     case OP_NOT:
212     case OP_NOTI:
213     case OP_STAR:
214     case OP_MINSTAR:
215     case OP_PLUS:
216     case OP_MINPLUS:
217     case OP_QUERY:
218     case OP_MINQUERY:
219     case OP_UPTO:
220     case OP_MINUPTO:
221     case OP_EXACT:
222     case OP_POSSTAR:
223     case OP_POSPLUS:
224     case OP_POSQUERY:
225     case OP_POSUPTO:
226     case OP_STARI:
227     case OP_MINSTARI:
228     case OP_PLUSI:
229     case OP_MINPLUSI:
230     case OP_QUERYI:
231     case OP_MINQUERYI:
232     case OP_UPTOI:
233     case OP_MINUPTOI:
234     case OP_EXACTI:
235     case OP_POSSTARI:
236     case OP_POSPLUSI:
237     case OP_POSQUERYI:
238     case OP_POSUPTOI:
239     case OP_NOTSTAR:
240     case OP_NOTMINSTAR:
241     case OP_NOTPLUS:
242     case OP_NOTMINPLUS:
243     case OP_NOTQUERY:
244     case OP_NOTMINQUERY:
245     case OP_NOTUPTO:
246     case OP_NOTMINUPTO:
247     case OP_NOTEXACT:
248     case OP_NOTPOSSTAR:
249     case OP_NOTPOSPLUS:
250     case OP_NOTPOSQUERY:
251     case OP_NOTPOSUPTO:
252     case OP_NOTSTARI:
253     case OP_NOTMINSTARI:
254     case OP_NOTPLUSI:
255     case OP_NOTMINPLUSI:
256     case OP_NOTQUERYI:
257     case OP_NOTMINQUERYI:
258     case OP_NOTUPTOI:
259     case OP_NOTMINUPTOI:
260     case OP_NOTEXACTI:
261     case OP_NOTPOSSTARI:
262     case OP_NOTPOSPLUSI:
263     case OP_NOTPOSQUERYI:
264     case OP_NOTPOSUPTOI:
265     if (utf) utf16_char = TRUE;
266 #endif
267     /* Fall through. */
268
269     default:
270     length = PRIV(OP_lengths)[*ptr] - 1;
271     break;
272
273     case OP_CLASS:
274     case OP_NCLASS:
275     /* Skip the character bit map. */
276     ptr += 32/sizeof(pcre_uchar);
277     length = 0;
278     break;
279
280     case OP_XCLASS:
281     /* Reverse the size of the XCLASS instance. */
282     ptr++;
283 #if defined COMPILE_PCRE16
284     *ptr = swap_uint16(*ptr);
285 #elif defined COMPILE_PCRE32
286     *ptr = swap_uint32(*ptr);
287 #endif
288 #ifndef COMPILE_PCRE32
289     if (LINK_SIZE > 1)
290       {
291       /* LINK_SIZE can be 1 or 2 in 16 bit mode. */
292       ptr++;
293       *ptr = swap_uint16(*ptr);
294       }
295 #endif
296     ptr++;
297     length = (GET(ptr, -LINK_SIZE)) - (1 + LINK_SIZE + 1);
298 #if defined COMPILE_PCRE16
299     *ptr = swap_uint16(*ptr);
300 #elif defined COMPILE_PCRE32
301     *ptr = swap_uint32(*ptr);
302 #endif
303     if ((*ptr & XCL_MAP) != 0)
304       {
305       /* Skip the character bit map. */
306       ptr += 32/sizeof(pcre_uchar);
307       length -= 32/sizeof(pcre_uchar);
308       }
309     break;
310     }
311   ptr++;
312   }
313 /* Control should never reach here in 16/32 bit mode. */
314 #else  /* In 8-bit mode, the pattern does not need to be processed. */
315 return 0;
316 #endif /* !COMPILE_PCRE8 */
317 }
318
319 /* End of pcre_byte_order.c */