Skip to content

Commit 917570a

Browse files
committed
common BUGFIX free cached pattern pcodes
... in case the patterns were only temporary. Fixes sysrepo/sysrepo#3680
1 parent 2d749a2 commit 917570a

File tree

6 files changed

+57
-6
lines changed

6 files changed

+57
-6
lines changed

src/ly_common.c

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,8 +304,10 @@ ly_ctx_shared_data_remove_and_free(struct ly_ctx_shared_data *shared_data)
304304
return;
305305
}
306306

307-
/* free members */
307+
/* free all the cached pattern pcodes */
308308
lyht_free(shared_data->pattern_ht, ly_ctx_ht_pattern_free_cb);
309+
310+
/* free rest of the members */
309311
lydict_clean(shared_data->data_dict);
310312
free(shared_data->data_dict);
311313
lyht_free(shared_data->leafref_links_ht, ly_ctx_ht_leafref_links_rec_free);
@@ -543,7 +545,7 @@ ly_ctx_data_del(const struct ly_ctx *ctx)
543545
}
544546

545547
LY_ERR
546-
ly_ctx_get_or_compile_pattern_code(const struct ly_ctx *ctx, const char *pattern, const pcre2_code **pcode)
548+
ly_ctx_shared_data_pattern_get(const struct ly_ctx *ctx, const char *pattern, const pcre2_code **pcode)
547549
{
548550
LY_ERR rc = LY_SUCCESS;
549551
struct ly_ctx_shared_data *ctx_data;
@@ -593,6 +595,37 @@ ly_ctx_get_or_compile_pattern_code(const struct ly_ctx *ctx, const char *pattern
593595
return rc;
594596
}
595597

598+
void
599+
ly_ctx_shared_data_pattern_del(const struct ly_ctx *ctx, const char *pattern)
600+
{
601+
struct ly_ctx_shared_data *ctx_data;
602+
struct ly_pattern_ht_rec rec = {0}, *found_rec = NULL;
603+
uint32_t hash;
604+
605+
assert(ctx && pattern);
606+
607+
/* get the context shared data */
608+
ctx_data = ly_ctx_shared_data_get(ctx);
609+
LY_CHECK_ERR_RET(!ctx_data, LOGINT(ctx), );
610+
611+
/* try to find the pattern code in the pattern ht */
612+
hash = lyht_hash(pattern, strlen(pattern));
613+
rec.pattern = pattern;
614+
615+
if (lyht_find(ctx_data->pattern_ht, &rec, hash, (void **)&found_rec)) {
616+
/* pattern code not cached yet */
617+
return;
618+
}
619+
620+
/* found it, free the pcode */
621+
pcre2_code_free(found_rec->pcode);
622+
623+
/* free the pattern HT record */
624+
if (lyht_remove(ctx_data->pattern_ht, &rec, hash)) {
625+
LOGINT(ctx);
626+
}
627+
}
628+
596629
void *
597630
ly_realloc(void *ptr, size_t size)
598631
{

src/ly_common.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ void ly_ctx_ht_leafref_links_rec_free(void *val_p);
474474
struct lys_module *ly_ctx_get_module_implemented2(const struct ly_ctx *ctx, const char *name, size_t name_len);
475475

476476
/**
477-
* @brief Get or compile a PCRE2 pattern code.
477+
* @brief Get a PCRE2 pattern code.
478478
*
479479
* If the pattern is not found in the context, it is compiled and cached.
480480
*
@@ -483,7 +483,15 @@ struct lys_module *ly_ctx_get_module_implemented2(const struct ly_ctx *ctx, cons
483483
* @param[out] pcode Optional compiled pattern code. DO NOT FREE IT, it is owned by the context.
484484
* @return LY_ERR value.
485485
*/
486-
LY_ERR ly_ctx_get_or_compile_pattern_code(const struct ly_ctx *ctx, const char *pattern, const pcre2_code **pcode);
486+
LY_ERR ly_ctx_shared_data_pattern_get(const struct ly_ctx *ctx, const char *pattern, const pcre2_code **pcode);
487+
488+
/**
489+
* @brief Free a PCRE2 pattern code, if found in the context cache.
490+
*
491+
* @param[in] ctx Context of the pattern.
492+
* @param[in] pattern Pattern string to use.
493+
*/
494+
void ly_ctx_shared_data_pattern_del(const struct ly_ctx *ctx, const char *pattern);
487495

488496
/******************************************************************************
489497
* Dictionary

src/parser_common.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ lyd_parser_notif_eventtime_validate(const struct lyd_node *node)
114114
/* validate */
115115
value = lyd_get_value(node);
116116
rc = lyplg_type_validate_patterns(ctx, patterns, value, strlen(value), &err);
117+
118+
/* free pcodes that were just cached */
119+
LY_ARRAY_FOR(patterns, u) {
120+
ly_ctx_shared_data_pattern_del(cctx.ctx, patterns[u]->expr);
121+
}
117122
}
118123

119124
cleanup:

src/plugins_types.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,7 @@ lyplg_type_validate_patterns(const struct ly_ctx *ctx, struct lysc_pattern **pat
552552
LY_ARRAY_FOR(patterns, u) {
553553
/* get (or compile) the compiled pattern. The pattern might not be found, because
554554
* if ctx is printed, it did not inherit compiled patterns from the original context. */
555-
LY_CHECK_RET(ly_ctx_get_or_compile_pattern_code(ctx, patterns[u]->expr, &pcode));
555+
LY_CHECK_RET(ly_ctx_shared_data_pattern_get(ctx, patterns[u]->expr, &pcode));
556556

557557
/* match the pattern */
558558
r = ly_pattern_code_match(pcode, str, str_len, err);

src/schema_compile_node.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1388,7 +1388,7 @@ lys_compile_type_patterns(struct lysc_ctx *ctx, const struct lysp_restr *pattern
13881388
++(*pattern)->refcount;
13891389

13901390
/* compile and insert the pattern into the context hash table, if it wasnt already compiled */
1391-
LY_CHECK_GOTO(ret = ly_ctx_get_or_compile_pattern_code(ctx->ctx, &patterns_p[u].arg.str[1], NULL), done);
1391+
LY_CHECK_GOTO(ret = ly_ctx_shared_data_pattern_get(ctx->ctx, &patterns_p[u].arg.str[1], NULL), done);
13921392

13931393
if (patterns_p[u].arg.str[0] == LYSP_RESTR_PATTERN_NACK) {
13941394
(*pattern)->inverted = 1;

src/xpath.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4997,6 +4997,7 @@ xpath_re_match(struct lyxp_set **args, uint32_t UNUSED(arg_count), struct lyxp_s
49974997
rc = lyxp_set_cast(args[1], LYXP_SET_STRING);
49984998
LY_CHECK_RET(rc);
49994999

5000+
/* create a temporary pattern */
50005001
LY_ARRAY_NEW_RET(set->ctx, patterns, pattern, LY_EMEM);
50015002
*pattern = calloc(1, sizeof **pattern);
50025003
if (set->cur_node) {
@@ -5007,9 +5008,13 @@ xpath_re_match(struct lyxp_set **args, uint32_t UNUSED(arg_count), struct lyxp_s
50075008
(*pattern)->expr = args[1]->val.str;
50085009
rc = lyplg_type_validate_patterns(set->ctx, patterns, args[0]->val.str, strlen(args[0]->val.str), &err);
50095010

5011+
/* free the pattern */
50105012
free(*pattern);
50115013
LY_ARRAY_FREE(patterns);
5014+
ly_ctx_shared_data_pattern_del(set->ctx, args[1]->val.str);
5015+
50125016
if (rc && (rc != LY_EVALID)) {
5017+
/* error */
50135018
ly_err_print(set->ctx, err);
50145019
ly_err_free(err);
50155020
return rc;

0 commit comments

Comments
 (0)