| /************************************************* |
| * Perl-Compatible Regular Expressions * |
| *************************************************/ |
| |
| /* PCRE is a library of functions to support regular expressions whose syntax |
| and semantics are as close as possible to those of the Perl 5 language. |
| |
| Written by Philip Hazel |
| Original API code Copyright (c) 1997-2012 University of Cambridge |
| New API code Copyright (c) 2016-2024 University of Cambridge |
| |
| ----------------------------------------------------------------------------- |
| Redistribution and use in source and binary forms, with or without |
| modification, are permitted provided that the following conditions are met: |
| |
| * Redistributions of source code must retain the above copyright notice, |
| this list of conditions and the following disclaimer. |
| |
| * Redistributions in binary form must reproduce the above copyright |
| notice, this list of conditions and the following disclaimer in the |
| documentation and/or other materials provided with the distribution. |
| |
| * Neither the name of the University of Cambridge nor the names of its |
| contributors may be used to endorse or promote products derived from |
| this software without specific prior written permission. |
| |
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
| LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| POSSIBILITY OF SUCH DAMAGE. |
| ----------------------------------------------------------------------------- |
| */ |
| |
| |
| #include "pcre2_internal.h" |
| |
| |
| |
| /************************************************* |
| * Default malloc/free functions * |
| *************************************************/ |
| |
| /* Ignore the "user data" argument in each case. */ |
| |
| static void *default_malloc(size_t size, void *data) |
| { |
| (void)data; |
| return malloc(size); |
| } |
| |
| |
| static void default_free(void *block, void *data) |
| { |
| (void)data; |
| free(block); |
| } |
| |
| |
| |
| /************************************************* |
| * Get a block and save memory control * |
| *************************************************/ |
| |
| /* This internal function is called to get a block of memory in which the |
| memory control data is to be stored at the start for future use. |
| |
| Arguments: |
| size amount of memory required |
| memctl pointer to a memctl block or NULL |
| |
| Returns: pointer to memory or NULL on failure |
| */ |
| |
| extern void * |
| PRIV(memctl_malloc)(size_t size, pcre2_memctl *memctl) |
| { |
| pcre2_memctl *newmemctl; |
| void *yield = (memctl == NULL)? malloc(size) : |
| memctl->malloc(size, memctl->memory_data); |
| if (yield == NULL) return NULL; |
| newmemctl = (pcre2_memctl *)yield; |
| if (memctl == NULL) |
| { |
| newmemctl->malloc = default_malloc; |
| newmemctl->free = default_free; |
| newmemctl->memory_data = NULL; |
| } |
| else *newmemctl = *memctl; |
| return yield; |
| } |
| |
| |
| |
| /************************************************* |
| * Create and initialize contexts * |
| *************************************************/ |
| |
| /* Initializing for compile and match contexts is done in separate, private |
| functions so that these can be called from functions such as pcre2_compile() |
| when an external context is not supplied. The initializing functions have an |
| option to set up default memory management. */ |
| |
| PCRE2_EXP_DEFN pcre2_general_context * PCRE2_CALL_CONVENTION |
| pcre2_general_context_create(void *(*private_malloc)(size_t, void *), |
| void (*private_free)(void *, void *), void *memory_data) |
| { |
| pcre2_general_context *gcontext; |
| if (private_malloc == NULL) private_malloc = default_malloc; |
| if (private_free == NULL) private_free = default_free; |
| gcontext = private_malloc(sizeof(pcre2_real_general_context), memory_data); |
| if (gcontext == NULL) return NULL; |
| gcontext->memctl.malloc = private_malloc; |
| gcontext->memctl.free = private_free; |
| gcontext->memctl.memory_data = memory_data; |
| return gcontext; |
| } |
| |
| |
| /* A default compile context is set up to save having to initialize at run time |
| when no context is supplied to the compile function. */ |
| |
| pcre2_compile_context PRIV(default_compile_context) = { |
| { default_malloc, default_free, NULL }, /* Default memory handling */ |
| NULL, /* Stack guard */ |
| NULL, /* Stack guard data */ |
| PRIV(default_tables), /* Character tables */ |
| PCRE2_UNSET, /* Max pattern length */ |
| PCRE2_UNSET, /* Max pattern compiled length */ |
| BSR_DEFAULT, /* Backslash R default */ |
| NEWLINE_DEFAULT, /* Newline convention */ |
| PARENS_NEST_LIMIT, /* As it says */ |
| 0, /* Extra options */ |
| MAX_VARLOOKBEHIND, /* As it says */ |
| PCRE2_OPTIMIZATION_ALL /* All optimizations enabled */ |
| }; |
| |
| /* The create function copies the default into the new memory, but must |
| override the default memory handling functions if a gcontext was provided. */ |
| |
| PCRE2_EXP_DEFN pcre2_compile_context * PCRE2_CALL_CONVENTION |
| pcre2_compile_context_create(pcre2_general_context *gcontext) |
| { |
| pcre2_compile_context *ccontext = PRIV(memctl_malloc)( |
| sizeof(pcre2_real_compile_context), (pcre2_memctl *)gcontext); |
| if (ccontext == NULL) return NULL; |
| *ccontext = PRIV(default_compile_context); |
| if (gcontext != NULL) |
| *((pcre2_memctl *)ccontext) = *((pcre2_memctl *)gcontext); |
| return ccontext; |
| } |
| |
| |
| /* A default match context is set up to save having to initialize at run time |
| when no context is supplied to a match function. */ |
| |
| pcre2_match_context PRIV(default_match_context) = { |
| { default_malloc, default_free, NULL }, |
| #ifdef SUPPORT_JIT |
| NULL, /* JIT callback */ |
| NULL, /* JIT callback data */ |
| #endif |
| NULL, /* Callout function */ |
| NULL, /* Callout data */ |
| NULL, /* Substitute callout function */ |
| NULL, /* Substitute callout data */ |
| NULL, /* Substitute case callout function */ |
| NULL, /* Substitute case callout data */ |
| PCRE2_UNSET, /* Offset limit */ |
| HEAP_LIMIT, |
| MATCH_LIMIT, |
| MATCH_LIMIT_DEPTH }; |
| |
| /* The create function copies the default into the new memory, but must |
| override the default memory handling functions if a gcontext was provided. */ |
| |
| PCRE2_EXP_DEFN pcre2_match_context * PCRE2_CALL_CONVENTION |
| pcre2_match_context_create(pcre2_general_context *gcontext) |
| { |
| pcre2_match_context *mcontext = PRIV(memctl_malloc)( |
| sizeof(pcre2_real_match_context), (pcre2_memctl *)gcontext); |
| if (mcontext == NULL) return NULL; |
| *mcontext = PRIV(default_match_context); |
| if (gcontext != NULL) |
| *((pcre2_memctl *)mcontext) = *((pcre2_memctl *)gcontext); |
| return mcontext; |
| } |
| |
| |
| /* A default convert context is set up to save having to initialize at run time |
| when no context is supplied to the convert function. */ |
| |
| pcre2_convert_context PRIV(default_convert_context) = { |
| { default_malloc, default_free, NULL }, /* Default memory handling */ |
| #ifdef _WIN32 |
| CHAR_BACKSLASH, /* Default path separator */ |
| CHAR_GRAVE_ACCENT /* Default escape character */ |
| #else /* Not Windows */ |
| CHAR_SLASH, /* Default path separator */ |
| CHAR_BACKSLASH /* Default escape character */ |
| #endif |
| }; |
| |
| /* The create function copies the default into the new memory, but must |
| override the default memory handling functions if a gcontext was provided. */ |
| |
| PCRE2_EXP_DEFN pcre2_convert_context * PCRE2_CALL_CONVENTION |
| pcre2_convert_context_create(pcre2_general_context *gcontext) |
| { |
| pcre2_convert_context *ccontext = PRIV(memctl_malloc)( |
| sizeof(pcre2_real_convert_context), (pcre2_memctl *)gcontext); |
| if (ccontext == NULL) return NULL; |
| *ccontext = PRIV(default_convert_context); |
| if (gcontext != NULL) |
| *((pcre2_memctl *)ccontext) = *((pcre2_memctl *)gcontext); |
| return ccontext; |
| } |
| |
| |
| /************************************************* |
| * Context copy functions * |
| *************************************************/ |
| |
| PCRE2_EXP_DEFN pcre2_general_context * PCRE2_CALL_CONVENTION |
| pcre2_general_context_copy(pcre2_general_context *gcontext) |
| { |
| pcre2_general_context *newcontext = |
| gcontext->memctl.malloc(sizeof(pcre2_real_general_context), |
| gcontext->memctl.memory_data); |
| if (newcontext == NULL) return NULL; |
| memcpy(newcontext, gcontext, sizeof(pcre2_real_general_context)); |
| return newcontext; |
| } |
| |
| |
| PCRE2_EXP_DEFN pcre2_compile_context * PCRE2_CALL_CONVENTION |
| pcre2_compile_context_copy(pcre2_compile_context *ccontext) |
| { |
| pcre2_compile_context *newcontext = |
| ccontext->memctl.malloc(sizeof(pcre2_real_compile_context), |
| ccontext->memctl.memory_data); |
| if (newcontext == NULL) return NULL; |
| memcpy(newcontext, ccontext, sizeof(pcre2_real_compile_context)); |
| return newcontext; |
| } |
| |
| |
| PCRE2_EXP_DEFN pcre2_match_context * PCRE2_CALL_CONVENTION |
| pcre2_match_context_copy(pcre2_match_context *mcontext) |
| { |
| pcre2_match_context *newcontext = |
| mcontext->memctl.malloc(sizeof(pcre2_real_match_context), |
| mcontext->memctl.memory_data); |
| if (newcontext == NULL) return NULL; |
| memcpy(newcontext, mcontext, sizeof(pcre2_real_match_context)); |
| return newcontext; |
| } |
| |
| |
| PCRE2_EXP_DEFN pcre2_convert_context * PCRE2_CALL_CONVENTION |
| pcre2_convert_context_copy(pcre2_convert_context *ccontext) |
| { |
| pcre2_convert_context *newcontext = |
| ccontext->memctl.malloc(sizeof(pcre2_real_convert_context), |
| ccontext->memctl.memory_data); |
| if (newcontext == NULL) return NULL; |
| memcpy(newcontext, ccontext, sizeof(pcre2_real_convert_context)); |
| return newcontext; |
| } |
| |
| |
| /************************************************* |
| * Context free functions * |
| *************************************************/ |
| |
| PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION |
| pcre2_general_context_free(pcre2_general_context *gcontext) |
| { |
| if (gcontext != NULL) |
| gcontext->memctl.free(gcontext, gcontext->memctl.memory_data); |
| } |
| |
| |
| PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION |
| pcre2_compile_context_free(pcre2_compile_context *ccontext) |
| { |
| if (ccontext != NULL) |
| ccontext->memctl.free(ccontext, ccontext->memctl.memory_data); |
| } |
| |
| |
| PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION |
| pcre2_match_context_free(pcre2_match_context *mcontext) |
| { |
| if (mcontext != NULL) |
| mcontext->memctl.free(mcontext, mcontext->memctl.memory_data); |
| } |
| |
| |
| PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION |
| pcre2_convert_context_free(pcre2_convert_context *ccontext) |
| { |
| if (ccontext != NULL) |
| ccontext->memctl.free(ccontext, ccontext->memctl.memory_data); |
| } |
| |
| |
| /************************************************* |
| * Set values in contexts * |
| *************************************************/ |
| |
| /* All these functions return 0 for success or PCRE2_ERROR_BADDATA if invalid |
| data is given. Only some of the functions are able to test the validity of the |
| data. */ |
| |
| |
| /* ------------ Compile context ------------ */ |
| |
| PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION |
| pcre2_set_character_tables(pcre2_compile_context *ccontext, |
| const uint8_t *tables) |
| { |
| ccontext->tables = tables; |
| return 0; |
| } |
| |
| PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION |
| pcre2_set_bsr(pcre2_compile_context *ccontext, uint32_t value) |
| { |
| switch(value) |
| { |
| case PCRE2_BSR_ANYCRLF: |
| case PCRE2_BSR_UNICODE: |
| ccontext->bsr_convention = value; |
| return 0; |
| |
| default: |
| return PCRE2_ERROR_BADDATA; |
| } |
| } |
| |
| PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION |
| pcre2_set_max_pattern_length(pcre2_compile_context *ccontext, PCRE2_SIZE length) |
| { |
| ccontext->max_pattern_length = length; |
| return 0; |
| } |
| |
| PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION |
| pcre2_set_max_pattern_compiled_length(pcre2_compile_context *ccontext, PCRE2_SIZE length) |
| { |
| ccontext->max_pattern_compiled_length = length; |
| return 0; |
| } |
| |
| PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION |
| pcre2_set_newline(pcre2_compile_context *ccontext, uint32_t newline) |
| { |
| switch(newline) |
| { |
| case PCRE2_NEWLINE_CR: |
| case PCRE2_NEWLINE_LF: |
| case PCRE2_NEWLINE_CRLF: |
| case PCRE2_NEWLINE_ANY: |
| case PCRE2_NEWLINE_ANYCRLF: |
| case PCRE2_NEWLINE_NUL: |
| ccontext->newline_convention = newline; |
| return 0; |
| |
| default: |
| return PCRE2_ERROR_BADDATA; |
| } |
| } |
| |
| PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION |
| pcre2_set_max_varlookbehind(pcre2_compile_context *ccontext, uint32_t limit) |
| { |
| ccontext->max_varlookbehind = limit; |
| return 0; |
| } |
| |
| PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION |
| pcre2_set_parens_nest_limit(pcre2_compile_context *ccontext, uint32_t limit) |
| { |
| ccontext->parens_nest_limit = limit; |
| return 0; |
| } |
| |
| PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION |
| pcre2_set_compile_extra_options(pcre2_compile_context *ccontext, uint32_t options) |
| { |
| ccontext->extra_options = options; |
| return 0; |
| } |
| |
| PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION |
| pcre2_set_compile_recursion_guard(pcre2_compile_context *ccontext, |
| int (*guard)(uint32_t, void *), void *user_data) |
| { |
| ccontext->stack_guard = guard; |
| ccontext->stack_guard_data = user_data; |
| return 0; |
| } |
| |
| PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION |
| pcre2_set_optimize(pcre2_compile_context *ccontext, uint32_t directive) |
| { |
| if (ccontext == NULL) |
| return PCRE2_ERROR_NULL; |
| |
| switch (directive) |
| { |
| case PCRE2_OPTIMIZATION_NONE: |
| ccontext->optimization_flags = 0; |
| break; |
| |
| case PCRE2_OPTIMIZATION_FULL: |
| ccontext->optimization_flags = PCRE2_OPTIMIZATION_ALL; |
| break; |
| |
| default: |
| if (directive >= PCRE2_AUTO_POSSESS && directive <= PCRE2_START_OPTIMIZE_OFF) |
| { |
| /* Even directive numbers starting from 64 switch a bit on; |
| * Odd directive numbers starting from 65 switch a bit off */ |
| if ((directive & 1) != 0) |
| ccontext->optimization_flags &= ~(1u << ((directive >> 1) - 32)); |
| else |
| ccontext->optimization_flags |= 1u << ((directive >> 1) - 32); |
| return 0; |
| } |
| return PCRE2_ERROR_BADOPTION; |
| } |
| |
| return 0; |
| } |
| |
| /* ------------ Match context ------------ */ |
| |
| PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION |
| pcre2_set_callout(pcre2_match_context *mcontext, |
| int (*callout)(pcre2_callout_block *, void *), void *callout_data) |
| { |
| mcontext->callout = callout; |
| mcontext->callout_data = callout_data; |
| return 0; |
| } |
| |
| PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION |
| pcre2_set_substitute_callout(pcre2_match_context *mcontext, |
| int (*substitute_callout)(pcre2_substitute_callout_block *, void *), |
| void *substitute_callout_data) |
| { |
| mcontext->substitute_callout = substitute_callout; |
| mcontext->substitute_callout_data = substitute_callout_data; |
| return 0; |
| } |
| |
| PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION |
| pcre2_set_substitute_case_callout(pcre2_match_context *mcontext, |
| PCRE2_SIZE (*substitute_case_callout)(PCRE2_SPTR, PCRE2_SIZE, PCRE2_UCHAR *, |
| PCRE2_SIZE, int, void *), |
| void *substitute_case_callout_data) |
| { |
| mcontext->substitute_case_callout = substitute_case_callout; |
| mcontext->substitute_case_callout_data = substitute_case_callout_data; |
| return 0; |
| } |
| |
| PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION |
| pcre2_set_heap_limit(pcre2_match_context *mcontext, uint32_t limit) |
| { |
| mcontext->heap_limit = limit; |
| return 0; |
| } |
| |
| PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION |
| pcre2_set_match_limit(pcre2_match_context *mcontext, uint32_t limit) |
| { |
| mcontext->match_limit = limit; |
| return 0; |
| } |
| |
| PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION |
| pcre2_set_depth_limit(pcre2_match_context *mcontext, uint32_t limit) |
| { |
| mcontext->depth_limit = limit; |
| return 0; |
| } |
| |
| PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION |
| pcre2_set_offset_limit(pcre2_match_context *mcontext, PCRE2_SIZE limit) |
| { |
| mcontext->offset_limit = limit; |
| return 0; |
| } |
| |
| /* These functions became obsolete at release 10.30. The first is kept as a |
| synonym for backwards compatibility. The second now does nothing. */ |
| |
| PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION |
| pcre2_set_recursion_limit(pcre2_match_context *mcontext, uint32_t limit) |
| { |
| return pcre2_set_depth_limit(mcontext, limit); |
| } |
| |
| PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION |
| pcre2_set_recursion_memory_management(pcre2_match_context *mcontext, |
| void *(*mymalloc)(size_t, void *), void (*myfree)(void *, void *), |
| void *mydata) |
| { |
| (void)mcontext; |
| (void)mymalloc; |
| (void)myfree; |
| (void)mydata; |
| return 0; |
| } |
| |
| |
| /* ------------ Convert context ------------ */ |
| |
| PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION |
| pcre2_set_glob_separator(pcre2_convert_context *ccontext, uint32_t separator) |
| { |
| if (separator != CHAR_SLASH && separator != CHAR_BACKSLASH && |
| separator != CHAR_DOT) return PCRE2_ERROR_BADDATA; |
| ccontext->glob_separator = separator; |
| return 0; |
| } |
| |
| static const char *globpunct = |
| STR_EXCLAMATION_MARK STR_QUOTATION_MARK STR_NUMBER_SIGN STR_DOLLAR_SIGN |
| STR_PERCENT_SIGN STR_AMPERSAND STR_APOSTROPHE STR_LEFT_PARENTHESIS |
| STR_RIGHT_PARENTHESIS STR_ASTERISK STR_PLUS STR_COMMA STR_MINUS STR_DOT |
| STR_SLASH STR_COLON STR_SEMICOLON STR_LESS_THAN_SIGN STR_EQUALS_SIGN |
| STR_GREATER_THAN_SIGN STR_QUESTION_MARK STR_COMMERCIAL_AT |
| STR_LEFT_SQUARE_BRACKET STR_BACKSLASH STR_RIGHT_SQUARE_BRACKET |
| STR_CIRCUMFLEX_ACCENT STR_UNDERSCORE STR_GRAVE_ACCENT STR_LEFT_CURLY_BRACKET |
| STR_VERTICAL_LINE STR_RIGHT_CURLY_BRACKET STR_TILDE; |
| |
| PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION |
| pcre2_set_glob_escape(pcre2_convert_context *ccontext, uint32_t escape) |
| { |
| if (escape > 255 || (escape != 0 && strchr(globpunct, escape) == NULL)) |
| return PCRE2_ERROR_BADDATA; |
| ccontext->glob_escape = escape; |
| return 0; |
| } |
| |
| /* End of pcre2_context.c */ |
| |