Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions src/context.c
Original file line number Diff line number Diff line change
Expand Up @@ -272,9 +272,9 @@ ly_ctx_ht_err_equal_cb(void *val1_p, void *val2_p, ly_bool UNUSED(mod), void *UN
static ly_bool
ly_ctx_ht_leafref_links_equal_cb(void *val1_p, void *val2_p, ly_bool UNUSED(mod), void *UNUSED(cb_data))
{
struct lyd_leafref_links_rec *rec1 = val1_p, *rec2 = val2_p;
struct lyd_leafref_links_rec **rec1 = val1_p, **rec2 = val2_p;

return rec1->node == rec2->node;
return (*rec1)->node == (*rec2)->node;
}

/**
Expand All @@ -285,9 +285,10 @@ ly_ctx_ht_leafref_links_equal_cb(void *val1_p, void *val2_p, ly_bool UNUSED(mod)
static void
ly_ctx_ht_leafref_links_rec_free(void *val_p)
{
struct lyd_leafref_links_rec *rec = val_p;
struct lyd_leafref_links_rec **rec = val_p;

lyd_free_leafref_links_rec(rec);
lyd_free_leafref_links_rec(*rec);
free(*rec);
}

LIBYANG_API_DEF LY_ERR
Expand Down Expand Up @@ -316,7 +317,12 @@ ly_ctx_new(const char *search_dir, uint16_t options, struct ly_ctx **new_ctx)
LY_CHECK_ERR_GOTO(lyplg_init(builtin_plugins_only), LOGINT(NULL); rc = LY_EINT, cleanup);

if (options & LY_CTX_LEAFREF_LINKING) {
ctx->leafref_links_ht = lyht_new(1, sizeof(struct lyd_leafref_links_rec), ly_ctx_ht_leafref_links_equal_cb, NULL, 1);
/**
* storing the pointer instead of record itself is needed to avoid invalid memory reads. Hash table can reallocate
* its memory completely during various manipulation function (e.g. remove, insert). In case of using pointers, the
* pointer can be reallocated safely, while record itself remains untouched and can be accessed/modified freely
* */
ctx->leafref_links_ht = lyht_new(1, sizeof(struct lyd_leafref_links_rec *), ly_ctx_ht_leafref_links_equal_cb, NULL, 1);
Comment thread
steweg marked this conversation as resolved.
LY_CHECK_ERR_GOTO(!ctx->leafref_links_ht, rc = LY_EMEM, cleanup);
}

Expand Down Expand Up @@ -654,7 +660,7 @@ ly_ctx_set_options(struct ly_ctx *ctx, uint16_t option)
}

if (!(ctx->flags & LY_CTX_LEAFREF_LINKING) && (option & LY_CTX_LEAFREF_LINKING)) {
ctx->leafref_links_ht = lyht_new(1, sizeof(struct lyd_leafref_links_rec), ly_ctx_ht_leafref_links_equal_cb, NULL, 1);
ctx->leafref_links_ht = lyht_new(1, sizeof(struct lyd_leafref_links_rec *), ly_ctx_ht_leafref_links_equal_cb, NULL, 1);
LY_CHECK_ERR_RET(!ctx->leafref_links_ht, LOGARG(ctx, option), LY_EMEM);
}

Expand Down
17 changes: 14 additions & 3 deletions src/tree_data.c
Original file line number Diff line number Diff line change
Expand Up @@ -3610,8 +3610,11 @@ LY_ERR
lyd_get_or_create_leafref_links_record(const struct lyd_node_term *node, struct lyd_leafref_links_rec **record, ly_bool create)
{
struct ly_ht *ht;
LY_ERR ret = LY_SUCCESS;
uint32_t hash;
struct lyd_leafref_links_rec rec = {0};
struct lyd_leafref_links_rec *rec_p = &rec;
struct lyd_leafref_links_rec **rec_p2;

assert(node);
assert(record);
Expand All @@ -3626,15 +3629,23 @@ lyd_get_or_create_leafref_links_record(const struct lyd_node_term *node, struct
ht = LYD_CTX(node)->leafref_links_ht;
hash = lyht_hash((const char *)&node, sizeof node);

if (lyht_find(ht, &rec, hash, (void **)record) == LY_ENOTFOUND) {
if (lyht_find(ht, &rec_p, hash, (void **)&rec_p2) == LY_ENOTFOUND) {
if (create) {
LY_CHECK_RET(lyht_insert_no_check(ht, &rec, hash, (void **)record));
rec_p = calloc(1, sizeof rec);
rec_p->node = node;
LY_CHECK_ERR_RET(!rec_p, LOGMEM(LYD_CTX(node)), LY_EMEM);
ret = lyht_insert_no_check(ht, &rec_p, hash, (void **)&rec_p2);
LY_CHECK_ERR_GOTO(ret, free(rec_p), cleanup);
} else {
return LY_ENOTFOUND;
}
}

return LY_SUCCESS;
cleanup:
if (!ret) {
*record = *rec_p2;
}
return ret;
}

LIBYANG_API_DEF LY_ERR
Expand Down
3 changes: 2 additions & 1 deletion src/tree_data_free.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,8 @@ lyd_free_leafref_nodes(const struct lyd_node_term *node)
/* free entry itself from hash table */
ht = LYD_CTX(node)->leafref_links_ht;
hash = lyht_hash((const char *)&node, sizeof node);
lyht_remove(ht, rec, hash);
lyht_remove(ht, &rec, hash);
free(rec);
}

/**
Expand Down