From ff4be30656bf105ca9599feae8198790eb7f9c45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 28 Sep 2026 10:22:07 -0400 Subject: [PATCH] Covered the control block ID cleared when module memory is given back (#779) The control block ID that _txm_module_manager_object_deallocate clears on its way out is read by the size-based object check, which is the one kept for dispatchers outside this repository. Nothing exercised that path. The expectations covering the clearing all went through object authentication, which consults the kernel's created list and would refuse a recycled address whatever its ID said, so they would have passed with the clearing removed. A section drives the size-based check directly. A module plants the value of an ID into memory it owns, gives the allocation back, and is handed the same address again; the check accepts the planted ID before the deallocation and refuses it afterwards, which is the difference the clearing makes. The authentication test holds 125 expectations and passes. Removing the ID clearing fails it. The full suite passes 107/107 in default_build_coverage with no warnings. Assisted-by: Claude Code (Opus 5) --- ...odule_manager_object_authentication_test.c | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/test/tx/module_manager/threadx_module_manager_object_authentication_test.c b/test/tx/module_manager/threadx_module_manager_object_authentication_test.c index 576ed532..6c79efae 100644 --- a/test/tx/module_manager/threadx_module_manager_object_authentication_test.c +++ b/test/tx/module_manager/threadx_module_manager_object_authentication_test.c @@ -886,6 +886,44 @@ char description[128]; _tx_thread_current_ptr = TX_NULL; + /**********************************************************************/ + /* The control block ID in memory the manager gives back. */ + /**********************************************************************/ + + /* Authentication reads the kernel's created list, so it refuses a recycled + address whatever the words in it say. The size-based check is the one that + reads the control block ID, and it is kept for dispatchers outside this + repository, so clearing the ID on the way out is what stops memory a module + wrote an ID into presenting that ID to whoever holds the address next. */ + + test_reset(&module_a, &module_b); + + kind = &test_object_kinds[4]; + raw_object = test_allocate(&module_a, kind -> test_kind_size); + + _tx_thread_current_ptr = (TX_THREAD *) test_allocate(&module_a, (ULONG) sizeof(TX_THREAD)); + _tx_thread_current_ptr -> tx_thread_module_instance_ptr = &module_a; + + (VOID) test_plant(raw_object, ((ULONG) 0), kind -> test_kind_id); + + test_expect("memory carrying a planted ID reads as an object of that type", + (ULONG) _txm_module_manager_object_id_check((ALIGN_TYPE) raw_object, TXM_QUEUE_OBJECT), + (ULONG) TX_TRUE); + + test_release_size(kind -> test_kind_size); + status = _txm_module_manager_object_deallocate(raw_object); + test_expect("the allocation is given back", (ULONG) status, (ULONG) TX_SUCCESS); + + object = test_allocate(&module_a, kind -> test_kind_size); + test_expect("the address comes round again", + (ULONG) (object == raw_object), (ULONG) TX_TRUE); + + test_expect("and no longer reads as an object of that type", + (ULONG) _txm_module_manager_object_id_check((ALIGN_TYPE) object, TXM_QUEUE_OBJECT), + (ULONG) TX_FALSE); + + _tx_thread_current_ptr = TX_NULL; + /**********************************************************************/ /* Objects the application owns, and objects nobody owns. */ /**********************************************************************/