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) <noreply@anthropic.com>
This commit is contained in:
Frédéric Desbiens
2026-09-28 10:22:07 -04:00
committed by GitHub
parent 2930618cfe
commit ff4be30656
@@ -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. */
/**********************************************************************/