diff --git a/include/refcount.h b/include/refcount.h index 785b052..533fdfe 100644 --- a/include/refcount.h +++ b/include/refcount.h @@ -31,10 +31,11 @@ /* An opaque type. You must not access these values directly. */ typedef unsigned int refcount_t; -/* Initialize REF with REFERENCES. */ +/* Initialize REF with REFERENCES. REFERENCES must not be zero. */ static inline void refcount_init (refcount_t *ref, unsigned int references) { + assert (references > 0 || !"references must not be zero!"); *ref = references; } @@ -47,6 +48,7 @@ refcount_ref (refcount_t *ref) unsigned int r; r = __atomic_add_fetch (ref, 1, __ATOMIC_RELAXED); assert (r != UINT_MAX || !"refcount overflowed!"); + assert (r != 1 || !"refcount detected use after free!"); return r; } @@ -101,10 +103,12 @@ union _references { uint64_t value; }; -/* Initialize REF with HARD and WEAK references. */ +/* Initialize REF with HARD and WEAK references. HARD and WEAK must + not both be zero. */ static inline void refcounts_init (refcounts_t *ref, uint32_t hard, uint32_t weak) { + assert ((hard != 0 || weak != 0) || !"references must not both be zero!"); ref->references = (struct references) { .hard = hard, .weak = weak }; } @@ -119,6 +123,8 @@ refcounts_ref (refcounts_t *ref, struct references *result) union _references r; r.value = __atomic_add_fetch (&ref->value, op.value, __ATOMIC_RELAXED); assert (r.references.hard != UINT32_MAX || !"refcount overflowed!"); + assert (! (r.references.hard == 1 && r.references.weak == 0) + || !"refcount detected use after free!"); if (result) *result = r.references; } @@ -208,6 +214,8 @@ refcounts_ref_weak (refcounts_t *ref, struct references *result) union _references r; r.value = __atomic_add_fetch (&ref->value, op.value, __ATOMIC_RELAXED); assert (r.references.weak != UINT32_MAX || !"refcount overflowed!"); + assert (! (r.references.hard == 0 && r.references.weak == 1) + || !"refcount detected use after free!"); if (result) *result = r.references; }