allocator: token_alloc tweaks Document what we expect callers to do, and make our examples comply, but also explicitly initialize the unsealed pointer for defense in depth.
diff --git a/examples/05.sealing/identifier.cc b/examples/05.sealing/identifier.cc index c66db96..08b2c5d 100644 --- a/examples/05.sealing/identifier.cc +++ b/examples/05.sealing/identifier.cc
@@ -36,7 +36,7 @@ // capabilities. auto [unsealed, sealed] = blocking_forever<token_allocate<Identifier>>(MALLOC_CAPABILITY, key()); - if (sealed == nullptr) + if (!sealed.is_valid()) { return nullptr; }
diff --git a/sdk/include/token.h b/sdk/include/token.h index 76aec99..b1e2a09 100644 --- a/sdk/include/token.h +++ b/sdk/include/token.h
@@ -190,14 +190,20 @@ /** * Type-safe helper to allocate a sealed `T*`. Returns the sealed and unsealed * pointers. + * + * Callers should check the sealed capability's tag to determine success. */ template<typename T> __always_inline std::pair<T *, Sealed<T>> token_allocate(Timeout *timeout, struct SObjStruct *heapCapability, SKey key) { - void *unsealed; - SObj sealed = token_sealed_unsealed_alloc( - timeout, heapCapability, key, sizeof(T), &unsealed); + /* + * Explicitly initialize unsealed, since callers like to check it, and not + * the sealed result, for validity. + */ + void *unsealed = nullptr; + SObj sealed = token_sealed_unsealed_alloc( + timeout, heapCapability, key, sizeof(T), &unsealed); return {static_cast<T *>(unsealed), Sealed<T>{sealed}}; }
diff --git a/sdk/lib/queue/queue_compartment.cc b/sdk/lib/queue/queue_compartment.cc index 9aec00a..4ed5f52 100644 --- a/sdk/lib/queue/queue_compartment.cc +++ b/sdk/lib/queue/queue_compartment.cc
@@ -186,7 +186,7 @@ } auto [unsealed, sealed] = token_allocate<RestrictedEndpoint>( timeout, heapCapability, receive_key()); - if (!unsealed) + if (!sealed.is_valid()) { return -ENOMEM; } @@ -208,7 +208,7 @@ } auto [unsealed, sealed] = token_allocate<RestrictedEndpoint>(timeout, heapCapability, send_key()); - if (!unsealed) + if (!sealed.is_valid()) { return -ENOMEM; }