Added missing free actions in some cases; other fixes.
h3rald h3rald@h3rald.com
Thu, 25 Jun 2026 11:02:14 +0200
4 files changed,
20 insertions(+),
18 deletions(-)
M
src/hex.c
→
src/hex.c
@@ -1158,9 +1158,8 @@ /*
* hex_set_symbol * Ownership contract: * - Caller passes a heap-allocated hex_item_t* (value). - * - This function ALWAYS consumes (frees) the passed pointer, whether it succeeds or fails. - * - The registry stores its own deep copy (value_copy) and becomes sole owner. - * - Callers MUST NOT use or free the original pointer after calling. + * - The registry stores its own deep copy and becomes sole owner. + * - Callers must not use or free the original pointer after calling. * - Rationale: prevents aliasing between caller's pointer and registry entry, eliminating * double free / accidental mutation risks. */@@ -3122,7 +3121,7 @@ (*size)--;
hex_debug(ctx, ">> PUSHQT[03]: <start> (items: %zu)", n_items); - hex_item_t **items = (hex_item_t **)malloc(n_items * sizeof(hex_item_t)); + hex_item_t **items = (hex_item_t **)malloc(n_items * sizeof(hex_item_t *)); if (!items) { hex_error(ctx, "[interpret bytecode quotation] Memory allocation failed");@@ -5473,10 +5472,7 @@ {
hex_error(ctx, "[symbol len] Quotation or string required"); result = 1; } - if (result != 0) - { - HEX_FREE(ctx, item); - } + HEX_FREE(ctx, item); return result; }@@ -5589,6 +5585,8 @@ HEX_FREE(ctx, list);
HEX_FREE(ctx, item); return 1; } + HEX_FREE(ctx, list); + HEX_FREE(ctx, item); return hex_push_integer(ctx, result); }@@ -6503,8 +6501,10 @@ HEX_POP(ctx, evalResult);
if (evalResult->type == HEX_TYPE_INTEGER && evalResult->data.int_value == 0) { // Don't free evalResult here as it might be shared - let normal cleanup handle it + HEX_FREE(ctx, evalResult); break; } + HEX_FREE(ctx, evalResult); hex_item_t *act = hex_copy_item(ctx, action); for (size_t i = 0; i < act->quotation_size; i++)@@ -6513,8 +6513,9 @@ // Create a copy to avoid ownership issues
hex_item_t *copy = hex_copy_item(ctx, act->data.quotation_value[i]); if (!copy || hex_push(ctx, copy) != 0) { - if (copy) + if (copy) { hex_free_item(ctx, copy); + } HEX_FREE(ctx, act); HEX_FREE(ctx, action); HEX_FREE(ctx, condition);
M
src/registry.c
→
src/registry.c
@@ -158,9 +158,8 @@ /*
* hex_set_symbol * Ownership contract: * - Caller passes a heap-allocated hex_item_t* (value). - * - This function ALWAYS consumes (frees) the passed pointer, whether it succeeds or fails. - * - The registry stores its own deep copy (value_copy) and becomes sole owner. - * - Callers MUST NOT use or free the original pointer after calling. + * - The registry stores its own deep copy and becomes sole owner. + * - Callers must not use or free the original pointer after calling. * - Rationale: prevents aliasing between caller's pointer and registry entry, eliminating * double free / accidental mutation risks. */
M
src/symbols.c
→
src/symbols.c
@@ -1443,10 +1443,7 @@ {
hex_error(ctx, "[symbol len] Quotation or string required"); result = 1; } - if (result != 0) - { - HEX_FREE(ctx, item); - } + HEX_FREE(ctx, item); return result; }@@ -1559,6 +1556,8 @@ HEX_FREE(ctx, list);
HEX_FREE(ctx, item); return 1; } + HEX_FREE(ctx, list); + HEX_FREE(ctx, item); return hex_push_integer(ctx, result); }@@ -2473,8 +2472,10 @@ HEX_POP(ctx, evalResult);
if (evalResult->type == HEX_TYPE_INTEGER && evalResult->data.int_value == 0) { // Don't free evalResult here as it might be shared - let normal cleanup handle it + HEX_FREE(ctx, evalResult); break; } + HEX_FREE(ctx, evalResult); hex_item_t *act = hex_copy_item(ctx, action); for (size_t i = 0; i < act->quotation_size; i++)@@ -2483,8 +2484,9 @@ // Create a copy to avoid ownership issues
hex_item_t *copy = hex_copy_item(ctx, act->data.quotation_value[i]); if (!copy || hex_push(ctx, copy) != 0) { - if (copy) + if (copy) { hex_free_item(ctx, copy); + } HEX_FREE(ctx, act); HEX_FREE(ctx, action); HEX_FREE(ctx, condition);
M
src/vm.c
→
src/vm.c
@@ -545,7 +545,7 @@ (*size)--;
hex_debug(ctx, ">> PUSHQT[03]: <start> (items: %zu)", n_items); - hex_item_t **items = (hex_item_t **)malloc(n_items * sizeof(hex_item_t)); + hex_item_t **items = (hex_item_t **)malloc(n_items * sizeof(hex_item_t *)); if (!items) { hex_error(ctx, "[interpret bytecode quotation] Memory allocation failed");