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