Skip to content

Fixed invalid memory read/segfault #2379

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 9, 2025
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);
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