Temporal Memory Safety

Temporal memory safety stops references being used after an object’s lifetime ends, including when its storage has been reused.

An object can be perfectly bounded and still be unsafe to use. If a program frees the object but keeps a copy of its capability, that copy has become stale. Using it later is a use-after-free error.

If the allocator gives the same storage to a new object, the stale reference may access data that did not exist when the capability was created. Preventing this is temporal memory safety.

Why bounds do not solve lifetime

Consider this sequence:

char *message = malloc(64);
char *stale = message;

free(message);
char *secret = malloc(64);

printf("%c\n", stale[0]);

The stale capability may still be tagged, bounded to 64 bytes, and permitted to read. If secret reuses the same address range, a bounds check alone cannot know that the logical object changed.

This is a different question from spatial safety:

Baseline CHERI behaviour

CHERI tags prevent software forging capabilities, but copying a valid capability creates another valid copy. Freeing memory does not automatically find and invalidate every copy in registers, stacks, heaps, message queues, or compartments.

General CHERI architectures therefore provide important building blocks but do not, by themselves, guarantee complete temporal safety for every allocator and software stack.

System-level approaches

Different environments can combine CHERI with one or more mechanisms:

Quarantine

Freed memory is held aside before reuse. This reduces the chance that a stale capability reaches a new object, but a finite quarantine may delay rather than eliminate reuse.

Revocation scans

The system finds capabilities that refer to a retired region and clears or invalidates them before reusing the memory. Tags make capabilities distinguishable from ordinary data, which can make precise scanning possible. The cost and concurrency model need careful design.

Epochs or generations

Memory reuse is associated with a changing generation, colour, or epoch. A stale reference carries an older value and fails when compared with the current allocation state. Implementations vary in where this metadata lives and how wraparound is handled.

Allocator and architecture support

An allocator can align, partition, and recycle memory in ways that work with capability bounds and revocation. Some processors or platforms add operations that accelerate this process.

Language-managed lifetime

Rust ownership, garbage collection, reference counting, or region-based allocation can prevent many stale references at a higher layer. Unsafe code, native interfaces, runtimes, and logic errors still need a complete system model.

CHERIoT

CHERIoT integrates temporal safety into its hardware-software design. Its allocator and revocation mechanisms are designed to prevent stale capabilities from gaining access to reallocated objects while meeting embedded-system constraints.

That does not mean every CHERI platform inherits the same mechanism. Name CHERIoT or the specific temporal-safety implementation when making the claim.

Compartment lifetimes

Temporal safety also applies to service handles and shared objects. If a compartment retains a capability after the caller destroys the object, memory safety depends on revoking or invalidating that delegated authority.

Interface design should specify:

Sealing can make a handle opaque, but does not by itself revoke every sealed copy.

Evaluating a temporal-safety claim

Ask:

  1. Which allocations and object types are covered?
  2. What happens to capabilities in registers and memory?
  3. Can memory be reused before revocation completes?
  4. How are concurrent readers handled?
  5. What is the cost in time, memory, and predictability?
  6. What happens on exhaustion, crash, or reset?
  7. Which tests or proofs support the claim?

Key takeaway

CHERI makes spatial authority explicit and capabilities identifiable. These properties provide a strong foundation for temporal safety, but object lifetime remains a system responsibility. Always distinguish architectural capability protection from the allocator, runtime, or operating-system mechanism that prevents reuse through stale references.

Where next

A media application may include millions of lines of code, dozens of libraries, and parsers for hostile input.

Compartmentalisation →