From f86e608fd0cdb81dd3d282405743e7fcbdd0a779 Mon Sep 17 00:00:00 2001 From: Sander Mertens Date: Wed, 11 Dec 2024 07:20:51 +0000 Subject: [PATCH] Fix memory leaks from casting non-trivial values --- distr/flecs.c | 10 +++++++++- distr/flecs.h | 2 +- include/flecs.h | 2 +- src/addons/script/expr/visit_fold.c | 10 +++++++++- test/script/src/Expr.c | 6 ++++++ 5 files changed, 26 insertions(+), 4 deletions(-) diff --git a/distr/flecs.c b/distr/flecs.c index 666676b6e..e8b5ac455 100644 --- a/distr/flecs.c +++ b/distr/flecs.c @@ -76088,7 +76088,9 @@ int flecs_expr_cast_visit_fold( return 0; } - ecs_meta_cursor_t cur = ecs_meta_cursor(script->world, dst_type, expr->ptr); + void *dst_ptr = ecs_value_new(script->world, dst_type); + + ecs_meta_cursor_t cur = ecs_meta_cursor(script->world, dst_type, dst_ptr); ecs_value_t value = { .type = src_type, .ptr = expr->ptr @@ -76096,10 +76098,16 @@ int flecs_expr_cast_visit_fold( if (ecs_meta_set_value(&cur, &value)) { flecs_expr_visit_error(script, node, "failed to assign value"); + ecs_value_free(script->world, dst_type, dst_ptr); goto error; } + if (expr->ptr != &expr->storage) { + ecs_value_free(script->world, expr->node.type, expr->ptr); + } + expr->node.type = dst_type; + expr->ptr = dst_ptr; node->expr = NULL; /* Prevent cleanup */ flecs_visit_fold_replace(script, node_ptr, (ecs_expr_node_t*)expr); diff --git a/distr/flecs.h b/distr/flecs.h index f7947fd65..7c4b9951e 100644 --- a/distr/flecs.h +++ b/distr/flecs.h @@ -265,7 +265,7 @@ * When enabled, Flecs will use the OS allocator provided in the OS API directly * instead of the builtin block allocator. This can decrease memory utilization * as memory will be freed more often, at the cost of decreased performance. */ -// #define FLECS_USE_OS_ALLOC +#define FLECS_USE_OS_ALLOC /** @def FLECS_ID_DESC_MAX * Maximum number of ids to add ecs_entity_desc_t / ecs_bulk_desc_t */ diff --git a/include/flecs.h b/include/flecs.h index 027abc239..ec96077c2 100644 --- a/include/flecs.h +++ b/include/flecs.h @@ -263,7 +263,7 @@ * When enabled, Flecs will use the OS allocator provided in the OS API directly * instead of the builtin block allocator. This can decrease memory utilization * as memory will be freed more often, at the cost of decreased performance. */ -// #define FLECS_USE_OS_ALLOC +#define FLECS_USE_OS_ALLOC /** @def FLECS_ID_DESC_MAX * Maximum number of ids to add ecs_entity_desc_t / ecs_bulk_desc_t */ diff --git a/src/addons/script/expr/visit_fold.c b/src/addons/script/expr/visit_fold.c index c6a62ec44..e641cee97 100644 --- a/src/addons/script/expr/visit_fold.c +++ b/src/addons/script/expr/visit_fold.c @@ -135,7 +135,9 @@ int flecs_expr_cast_visit_fold( return 0; } - ecs_meta_cursor_t cur = ecs_meta_cursor(script->world, dst_type, expr->ptr); + void *dst_ptr = ecs_value_new(script->world, dst_type); + + ecs_meta_cursor_t cur = ecs_meta_cursor(script->world, dst_type, dst_ptr); ecs_value_t value = { .type = src_type, .ptr = expr->ptr @@ -143,10 +145,16 @@ int flecs_expr_cast_visit_fold( if (ecs_meta_set_value(&cur, &value)) { flecs_expr_visit_error(script, node, "failed to assign value"); + ecs_value_free(script->world, dst_type, dst_ptr); goto error; } + if (expr->ptr != &expr->storage) { + ecs_value_free(script->world, expr->node.type, expr->ptr); + } + expr->node.type = dst_type; + expr->ptr = dst_ptr; node->expr = NULL; /* Prevent cleanup */ flecs_visit_fold_replace(script, node_ptr, (ecs_expr_node_t*)expr); diff --git a/test/script/src/Expr.c b/test/script/src/Expr.c index d1e354930..e754a3f55 100644 --- a/test/script/src/Expr.c +++ b/test/script/src/Expr.c @@ -1850,6 +1850,7 @@ void Expr_cond_eq_bool_int(void) { test_assert(ecs_expr_run(world, "true == 1", &v, NULL) != NULL); test_assert(v.type == ecs_id(ecs_bool_t)); test_assert(*(bool*)v.ptr == true); + ecs_value_free(world, v.type, v.ptr); } { @@ -1857,6 +1858,7 @@ void Expr_cond_eq_bool_int(void) { test_assert(ecs_expr_run(world, "true == 2", &v, NULL) != NULL); test_assert(v.type == ecs_id(ecs_bool_t)); test_assert(*(bool*)v.ptr == true); + ecs_value_free(world, v.type, v.ptr); } { @@ -1864,6 +1866,7 @@ void Expr_cond_eq_bool_int(void) { test_assert(ecs_expr_run(world, "true == 0", &v, NULL) != NULL); test_assert(v.type == ecs_id(ecs_bool_t)); test_assert(*(bool*)v.ptr == false); + ecs_value_free(world, v.type, v.ptr); } { @@ -1871,6 +1874,7 @@ void Expr_cond_eq_bool_int(void) { test_assert(ecs_expr_run(world, "false == 1", &v, NULL) != NULL); test_assert(v.type == ecs_id(ecs_bool_t)); test_assert(*(bool*)v.ptr == false); + ecs_value_free(world, v.type, v.ptr); } { @@ -1878,6 +1882,7 @@ void Expr_cond_eq_bool_int(void) { test_assert(ecs_expr_run(world, "false == 2", &v, NULL) != NULL); test_assert(v.type == ecs_id(ecs_bool_t)); test_assert(*(bool*)v.ptr == false); + ecs_value_free(world, v.type, v.ptr); } { @@ -1885,6 +1890,7 @@ void Expr_cond_eq_bool_int(void) { test_assert(ecs_expr_run(world, "false == 0", &v, NULL) != NULL); test_assert(v.type == ecs_id(ecs_bool_t)); test_assert(*(bool*)v.ptr == true); + ecs_value_free(world, v.type, v.ptr); } ecs_fini(world);