From 7277f89a5f0be91f1639c5cec0e414d2be69cf03 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Sat, 11 Jan 2025 14:05:56 +0000 Subject: [PATCH] parser: Compile regular expressions only once Signed-off-by: Michael Tremer --- src/pakfire/parser.c | 87 +++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 50 deletions(-) diff --git a/src/pakfire/parser.c b/src/pakfire/parser.c index 77c1491b0..b6a862f14 100644 --- a/src/pakfire/parser.c +++ b/src/pakfire/parser.c @@ -45,6 +45,12 @@ // Enable to get more debugging output //#define PAKFIRE_DEBUG_PARSER +// Regular expressions +static struct pakfire_parser_regexes { + pcre2_code* variable; + pcre2_code* command; +} regexes = {}; + struct pakfire_parser { struct pakfire_ctx* ctx; struct pakfire* pakfire; @@ -56,34 +62,8 @@ struct pakfire_parser { struct pakfire_parser_declaration** declarations; size_t num_declarations; - - // Regular expressions - pcre2_code* regex_command; - pcre2_code* regex_variable; }; -static int pakfire_parser_compile_regexes(struct pakfire_parser* parser) { - int r; - - // Commands - if (!parser->regex_command && (parser->flags & PAKFIRE_PARSER_FLAGS_EXPAND_COMMANDS)) { - r = pakfire_compile_regex(parser->ctx, &parser->regex_command, - "%(\\(((?>[^()]|(?1))*)\\))"); - if (r) - return r; - } - - // Variables - if (!parser->regex_variable) { - r = pakfire_compile_regex(parser->ctx, &parser->regex_variable, - "%\\{([A-Za-z0-9_\\-]+)\\}"); - if (r) - return r; - } - - return 0; -} - static void pakfire_parser_free_declaration(struct pakfire_parser_declaration* d) { if (d->value) free(d->value); @@ -101,12 +81,6 @@ static void pakfire_parser_free_declarations(struct pakfire_parser* parser) { } static void pakfire_parser_free(struct pakfire_parser* parser) { - // Release regular expressions - if (parser->regex_variable) - pcre2_code_free(parser->regex_variable); - if (parser->regex_command) - pcre2_code_free(parser->regex_command); - pakfire_parser_free_declarations(parser); if (parser->namespace) @@ -503,26 +477,35 @@ int pakfire_parser_append(struct pakfire_parser* parser, } static int pakfire_parser_expand_commands(struct pakfire_parser* parser, char** buffer) { - int r = 0; + pcre2_match_data* match = NULL; PCRE2_UCHAR* command = NULL; PCRE2_SIZE command_length; PCRE2_UCHAR* pattern = NULL; PCRE2_SIZE pattern_length; + int r = 0; DEBUG(parser->ctx, "Searching for commands in:\n%s\n", *buffer); + // Compile the regular expression + if (!regexes.command) { + r = pakfire_compile_regex(parser->ctx, ®exes.command, "%(\\(((?>[^()]|(?1))*)\\))"); + if (r < 0) { + ERROR(parser->ctx, "Failed to compile the command regex: %s\n", strerror(-r)); + goto ERROR; + } + } + // Allocate memory for results - pcre2_match_data* match = pcre2_match_data_create_from_pattern( - parser->regex_command, NULL); + match = pcre2_match_data_create_from_pattern(regexes.command, NULL); // Arguments passed to pakfire_execute const char* argv[4] = { "/bin/sh", "-c", NULL /* will be replaced by command later */, NULL, }; - while (1) { + for (;;) { // Perform matching - r = pcre2_jit_match(parser->regex_command, + r = pcre2_jit_match(regexes.command, (PCRE2_UCHAR*)*buffer, strlen(*buffer), 0, 0, match, NULL); // End loop when we have expanded all variables @@ -593,8 +576,8 @@ static int pakfire_parser_expand_commands(struct pakfire_parser* parser, char** } ERROR: - pcre2_match_data_free(match); - + if (match) + pcre2_match_data_free(match); if (command) pcre2_substring_free(command); if (pattern) @@ -605,6 +588,7 @@ ERROR: static int pakfire_parser_expand_variables(struct pakfire_parser* parser, const char* namespace, char** buffer) { + pcre2_match_data* match = NULL; PCRE2_UCHAR* variable = NULL; PCRE2_SIZE variable_length = 0; PCRE2_UCHAR* pattern = NULL; @@ -619,14 +603,22 @@ static int pakfire_parser_expand_variables(struct pakfire_parser* parser, else if (!*buffer) return 0; + // Compile the regular expression + if (!regexes.variable) { + r = pakfire_compile_regex(parser->ctx, ®exes.variable, "%\\{([A-Za-z0-9_\\-]+)\\}"); + if (r < 0) { + ERROR(parser->ctx, "Failed to compile the variable regex: %s\n", strerror(-r)); + goto ERROR; + } + } + // Allocate memory for results - pcre2_match_data* match = pcre2_match_data_create_from_pattern( - parser->regex_variable, NULL); + match = pcre2_match_data_create_from_pattern(regexes.variable, NULL); // Search for any variables - while (1) { + for (;;) { // Perform matching - r = pcre2_jit_match(parser->regex_variable, + r = pcre2_jit_match(regexes.variable, (PCRE2_UCHAR*)*buffer, strlen(*buffer), 0, 0, match, NULL); // End loop when we have expanded all variables @@ -711,6 +703,8 @@ ERROR: char* pakfire_parser_expand(struct pakfire_parser* parser, const char* namespace, const char* value) { + int r; + // Return NULL when the value is NULL if (!value) return NULL; @@ -723,13 +717,6 @@ char* pakfire_parser_expand(struct pakfire_parser* parser, if (!pos) return buffer; - // Compile all regular expressions - int r = pakfire_parser_compile_regexes(parser); - if (r) { - DEBUG(parser->ctx, "Could not compile regular expressions: %m\n"); - goto ERROR; - } - // Expand all variables r = pakfire_parser_expand_variables(parser, namespace, &buffer); if (r) { -- 2.47.3