1/*************************************************
2*      Perl-Compatible Regular Expressions       *
3*************************************************/
4
5/* PCRE is a library of functions to support regular expressions whose syntax
6and semantics are as close as possible to those of the Perl 5 language.
7
8                       Written by Philip Hazel
9     Original API code Copyright (c) 1997-2012 University of Cambridge
10         New API code Copyright (c) 2016 University of Cambridge
11
12-----------------------------------------------------------------------------
13Redistribution and use in source and binary forms, with or without
14modification, are permitted provided that the following conditions are met:
15
16    * Redistributions of source code must retain the above copyright notice,
17      this list of conditions and the following disclaimer.
18
19    * Redistributions in binary form must reproduce the above copyright
20      notice, this list of conditions and the following disclaimer in the
21      documentation and/or other materials provided with the distribution.
22
23    * Neither the name of the University of Cambridge nor the names of its
24      contributors may be used to endorse or promote products derived from
25      this software without specific prior written permission.
26
27THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
31LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37POSSIBILITY OF SUCH DAMAGE.
38-----------------------------------------------------------------------------
39*/
40
41/* This module contains functions for serializing and deserializing
42a sequence of compiled codes. */
43
44
45#ifdef HAVE_CONFIG_H
46#include "config.h"
47#endif
48
49
50#include "pcre2_internal.h"
51
52/* Magic number to provide a small check against being handed junk. */
53
54#define SERIALIZED_DATA_MAGIC 0x50523253u
55
56/* Deserialization is limited to the current PCRE version and
57character width. */
58
59#define SERIALIZED_DATA_VERSION \
60  ((PCRE2_MAJOR) | ((PCRE2_MINOR) << 16))
61
62#define SERIALIZED_DATA_CONFIG \
63  (sizeof(PCRE2_UCHAR) | ((sizeof(void*)) << 8) | ((sizeof(PCRE2_SIZE)) << 16))
64
65
66
67/*************************************************
68*           Serialize compiled patterns          *
69*************************************************/
70
71PCRE2_EXP_DEFN int32_t PCRE2_CALL_CONVENTION
72pcre2_serialize_encode(const pcre2_code **codes, int32_t number_of_codes,
73   uint8_t **serialized_bytes, PCRE2_SIZE *serialized_size,
74   pcre2_general_context *gcontext)
75{
76uint8_t *bytes;
77uint8_t *dst_bytes;
78int32_t i;
79PCRE2_SIZE total_size;
80const pcre2_real_code *re;
81const uint8_t *tables;
82pcre2_serialized_data *data;
83
84const pcre2_memctl *memctl = (gcontext != NULL) ?
85  &gcontext->memctl : &PRIV(default_compile_context).memctl;
86
87if (codes == NULL || serialized_bytes == NULL || serialized_size == NULL)
88  return PCRE2_ERROR_NULL;
89
90if (number_of_codes <= 0) return PCRE2_ERROR_BADDATA;
91
92/* Compute total size. */
93total_size = sizeof(pcre2_serialized_data) + tables_length;
94tables = NULL;
95
96for (i = 0; i < number_of_codes; i++)
97  {
98  if (codes[i] == NULL) return PCRE2_ERROR_NULL;
99  re = (const pcre2_real_code *)(codes[i]);
100  if (re->magic_number != MAGIC_NUMBER) return PCRE2_ERROR_BADMAGIC;
101  if (tables == NULL)
102    tables = re->tables;
103  else if (tables != re->tables)
104    return PCRE2_ERROR_MIXEDTABLES;
105  total_size += re->blocksize;
106  }
107
108/* Initialize the byte stream. */
109bytes = memctl->malloc(total_size + sizeof(pcre2_memctl), memctl->memory_data);
110if (bytes == NULL) return PCRE2_ERROR_NOMEMORY;
111
112/* The controller is stored as a hidden parameter. */
113memcpy(bytes, memctl, sizeof(pcre2_memctl));
114bytes += sizeof(pcre2_memctl);
115
116data = (pcre2_serialized_data *)bytes;
117data->magic = SERIALIZED_DATA_MAGIC;
118data->version = SERIALIZED_DATA_VERSION;
119data->config = SERIALIZED_DATA_CONFIG;
120data->number_of_codes = number_of_codes;
121
122/* Copy all compiled code data. */
123dst_bytes = bytes + sizeof(pcre2_serialized_data);
124memcpy(dst_bytes, tables, tables_length);
125dst_bytes += tables_length;
126
127for (i = 0; i < number_of_codes; i++)
128  {
129  re = (const pcre2_real_code *)(codes[i]);
130  memcpy(dst_bytes, (char *)re, re->blocksize);
131  dst_bytes += re->blocksize;
132  }
133
134*serialized_bytes = bytes;
135*serialized_size = total_size;
136return number_of_codes;
137}
138
139
140/*************************************************
141*          Deserialize compiled patterns         *
142*************************************************/
143
144PCRE2_EXP_DEFN int32_t PCRE2_CALL_CONVENTION
145pcre2_serialize_decode(pcre2_code **codes, int32_t number_of_codes,
146   const uint8_t *bytes, pcre2_general_context *gcontext)
147{
148const pcre2_serialized_data *data = (const pcre2_serialized_data *)bytes;
149const pcre2_memctl *memctl = (gcontext != NULL) ?
150  &gcontext->memctl : &PRIV(default_compile_context).memctl;
151
152const uint8_t *src_bytes;
153pcre2_real_code *dst_re;
154uint8_t *tables;
155int32_t i, j;
156
157/* Sanity checks. */
158
159if (data == NULL || codes == NULL) return PCRE2_ERROR_NULL;
160if (number_of_codes <= 0) return PCRE2_ERROR_BADDATA;
161if (data->number_of_codes <= 0) return PCRE2_ERROR_BADSERIALIZEDDATA;
162if (data->magic != SERIALIZED_DATA_MAGIC) return PCRE2_ERROR_BADMAGIC;
163if (data->version != SERIALIZED_DATA_VERSION) return PCRE2_ERROR_BADMODE;
164if (data->config != SERIALIZED_DATA_CONFIG) return PCRE2_ERROR_BADMODE;
165
166if (number_of_codes > data->number_of_codes)
167  number_of_codes = data->number_of_codes;
168
169src_bytes = bytes + sizeof(pcre2_serialized_data);
170
171/* Decode tables. The reference count for the tables is stored immediately
172following them. */
173
174tables = memctl->malloc(tables_length + sizeof(PCRE2_SIZE), memctl->memory_data);
175if (tables == NULL) return PCRE2_ERROR_NOMEMORY;
176
177memcpy(tables, src_bytes, tables_length);
178*(PCRE2_SIZE *)(tables + tables_length) = number_of_codes;
179src_bytes += tables_length;
180
181/* Decode the byte stream. We must not try to read the size from the compiled
182code block in the stream, because it might be unaligned, which causes errors on
183hardware such as Sparc-64 that doesn't like unaligned memory accesses. The type
184of the blocksize field is given its own name to ensure that it is the same here
185as in the block. */
186
187for (i = 0; i < number_of_codes; i++)
188  {
189  CODE_BLOCKSIZE_TYPE blocksize;
190  memcpy(&blocksize, src_bytes + offsetof(pcre2_real_code, blocksize),
191    sizeof(CODE_BLOCKSIZE_TYPE));
192  if (blocksize <= sizeof(pcre2_real_code))
193    return PCRE2_ERROR_BADSERIALIZEDDATA;
194
195  /* The allocator provided by gcontext replaces the original one. */
196
197  dst_re = (pcre2_real_code *)PRIV(memctl_malloc)(blocksize,
198    (pcre2_memctl *)gcontext);
199  if (dst_re == NULL)
200    {
201    memctl->free(tables, memctl->memory_data);
202    for (j = 0; j < i; j++)
203      {
204      memctl->free(codes[j], memctl->memory_data);
205      codes[j] = NULL;
206      }
207    return PCRE2_ERROR_NOMEMORY;
208    }
209
210  /* The new allocator must be preserved. */
211
212  memcpy(((uint8_t *)dst_re) + sizeof(pcre2_memctl),
213    src_bytes + sizeof(pcre2_memctl), blocksize - sizeof(pcre2_memctl));
214  if (dst_re->magic_number != MAGIC_NUMBER ||
215      dst_re->name_entry_size > MAX_NAME_SIZE + IMM2_SIZE + 1 ||
216      dst_re->name_count > MAX_NAME_COUNT)
217    return PCRE2_ERROR_BADSERIALIZEDDATA;
218
219  /* At the moment only one table is supported. */
220
221  dst_re->tables = tables;
222  dst_re->executable_jit = NULL;
223  dst_re->flags |= PCRE2_DEREF_TABLES;
224
225  codes[i] = dst_re;
226  src_bytes += blocksize;
227  }
228
229return number_of_codes;
230}
231
232
233/*************************************************
234*    Get the number of serialized patterns       *
235*************************************************/
236
237PCRE2_EXP_DEFN int32_t PCRE2_CALL_CONVENTION
238pcre2_serialize_get_number_of_codes(const uint8_t *bytes)
239{
240const pcre2_serialized_data *data = (const pcre2_serialized_data *)bytes;
241
242if (data == NULL) return PCRE2_ERROR_NULL;
243if (data->magic != SERIALIZED_DATA_MAGIC) return PCRE2_ERROR_BADMAGIC;
244if (data->version != SERIALIZED_DATA_VERSION) return PCRE2_ERROR_BADMODE;
245if (data->config != SERIALIZED_DATA_CONFIG) return PCRE2_ERROR_BADMODE;
246
247return data->number_of_codes;
248}
249
250
251/*************************************************
252*            Free the allocated stream           *
253*************************************************/
254
255PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION
256pcre2_serialize_free(uint8_t *bytes)
257{
258if (bytes != NULL)
259  {
260  pcre2_memctl *memctl = (pcre2_memctl *)(bytes - sizeof(pcre2_memctl));
261  memctl->free(memctl, memctl->memory_data);
262  }
263}
264
265/* End of pcre2_serialize.c */
266