diff --git a/scripts/memory-core-baseline.txt b/scripts/memory-core-baseline.txt index d3c3ef8bd..eaf1e759c 100644 --- a/scripts/memory-core-baseline.txt +++ b/scripts/memory-core-baseline.txt @@ -16,7 +16,7 @@ internal/cbm/sqlite_writer.c 74 src/cli/activation_transaction.c 80 src/cli/agent_clients.c 73 src/cli/agent_profiles.c 7 -src/cli/cli.c 170 +src/cli/cli.c 166 src/cli/client_adapter.c 3 src/cli/config_edit_path.c 2 src/cli/config_json_like.c 142 diff --git a/src/cli/cli.c b/src/cli/cli.c index c03d4499f..ba4ae520a 100644 --- a/src/cli/cli.c +++ b/src/cli/cli.c @@ -22,6 +22,7 @@ #include "foundation/compat.h" #include "foundation/platform.h" #include "foundation/constants.h" +#include "foundation/json_writer.h" #include "foundation/log.h" #include "foundation/mem_core.h" #include "foundation/sha256.h" @@ -4242,7 +4243,8 @@ static bool cbm_copilot_add_hook_event(yyjson_mut_doc *doc, yyjson_mut_val *hook /* include_posttool renders the current manifest; without it the function * renders the previous lifecycle-only manifest, which installs up to v0.12 wrote - * and which upgrades and uninstalls must still recognize as owned. */ + * and which upgrades and uninstalls must still recognize as owned. The result is + * released with cbm_free(CBM_MEM_CLASS_OTHER, ...). */ static char *cbm_build_copilot_hook_manifest(const char *binary_path, bool include_posttool) { char session_bash[CLI_BUF_8K]; char session_powershell[CLI_BUF_8K]; @@ -4284,7 +4286,9 @@ static char *cbm_build_copilot_hook_manifest(const char *binary_path, bool inclu cbm_copilot_add_hook_event(doc, hooks, "PostToolUse", COPILOT_SEARCH_MATCHER, post_bash, post_powershell)) && yyjson_mut_obj_add_val(doc, root, "hooks", hooks); - char *manifest = ok ? yyjson_mut_write(doc, YYJSON_WRITE_PRETTY, NULL) : NULL; + char *manifest = ok ? yyjson_mut_write_opts(doc, YYJSON_WRITE_PRETTY, + cbm_json_writer_allocator(), NULL, NULL) + : NULL; yyjson_mut_doc_free(doc); return manifest; } @@ -4303,14 +4307,14 @@ static int cbm_upsert_copilot_hooks(const char *binary_path, const char *manifes char *manifest = cbm_build_copilot_hook_manifest(binary_path, true); char *previous = cbm_build_copilot_hook_manifest(binary_path, false); if (!manifest || !previous || !manifest_path) { - free(manifest); - free(previous); + cbm_free(CBM_MEM_CLASS_OTHER, manifest); + cbm_free(CBM_MEM_CLASS_OTHER, previous); return CLI_ERR; } const char *const released[] = {previous}; int rc = cbm_text_migrate_owned_document(manifest_path, manifest, released, 1U); - free(manifest); - free(previous); + cbm_free(CBM_MEM_CLASS_OTHER, manifest); + cbm_free(CBM_MEM_CLASS_OTHER, previous); return rc == 0 ? CLI_OK : CLI_ERR; } @@ -4318,14 +4322,14 @@ static int cbm_remove_copilot_hooks(const char *manifest_path, const char *binar char *manifest = cbm_build_copilot_hook_manifest(binary_path, true); char *previous = cbm_build_copilot_hook_manifest(binary_path, false); if (!manifest || !previous || !manifest_path) { - free(manifest); - free(previous); + cbm_free(CBM_MEM_CLASS_OTHER, manifest); + cbm_free(CBM_MEM_CLASS_OTHER, previous); return CLI_ERR; } const char *const released[] = {previous}; int rc = cbm_text_remove_owned_document_any(manifest_path, manifest, released, 1U); - free(manifest); - free(previous); + cbm_free(CBM_MEM_CLASS_OTHER, manifest); + cbm_free(CBM_MEM_CLASS_OTHER, previous); return rc >= 0 ? CLI_OK : CLI_ERR; } diff --git a/src/cli/cli.h b/src/cli/cli.h index e94d7e227..4d32873ca 100644 --- a/src/cli/cli.h +++ b/src/cli/cli.h @@ -283,7 +283,8 @@ bool cbm_hook_path_contains_for_testing(const char *root, const char *candidate, bool case_insensitive); const char *cbm_hook_no_project_index_guidance_for_testing(const char *event); bool cbm_hook_augment_parse_bash_pattern_for_testing(const char *cmd, char *out, size_t out_sz); -/* include_posttool false renders the previous lifecycle-only manifest. */ +/* include_posttool false renders the previous lifecycle-only manifest. Release + * the result with cbm_free(CBM_MEM_CLASS_OTHER, ...). */ char *cbm_build_copilot_hook_manifest_for_testing(const char *binary_path, bool include_posttool); bool cbm_mcp_command_path_probe_safe_for_testing(const char *command, bool windows); void cbm_set_mcp_command_path_probe_counter_for_testing(int *counter); diff --git a/tests/test_cli.c b/tests/test_cli.c index a8e650bfe..9853761cb 100644 --- a/tests/test_cli.c +++ b/tests/test_cli.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -12907,8 +12908,8 @@ TEST(cli_copilot_manifest_adds_posttooluse_search_hook) { bool previous_shape = strstr(previous, "sessionStart") && strstr(previous, "subagentStart") && !strstr(previous, "PostToolUse"); yyjson_doc_free(doc); - free(current); - free(previous); + cbm_free(CBM_MEM_CLASS_OTHER, current); + cbm_free(CBM_MEM_CLASS_OTHER, previous); if (!shaped || !previous_shape) FAIL("Copilot manifest must add one PostToolUse search hook beside the lifecycle pair"); PASS(); @@ -12939,8 +12940,8 @@ TEST(cli_copilot_install_upgrades_previous_manifest) { char *previous = cbm_build_copilot_hook_manifest_for_testing(binary, false); char *current = cbm_build_copilot_hook_manifest_for_testing(binary, true); if (!previous || !current) { - free(previous); - free(current); + cbm_free(CBM_MEM_CLASS_OTHER, previous); + cbm_free(CBM_MEM_CLASS_OTHER, current); test_rmdir_r(tmpdir); FAIL("Copilot manifest rendering failed"); } @@ -12967,8 +12968,8 @@ TEST(cli_copilot_install_upgrades_previous_manifest) { free(upgraded); free(again); - free(previous); - free(current); + cbm_free(CBM_MEM_CLASS_OTHER, previous); + cbm_free(CBM_MEM_CLASS_OTHER, current); restore_test_env("HOME", saved_home); restore_test_env("PATH", saved_path); restore_test_env("COPILOT_HOME", saved_copilot);