In dict_insert(), the read lock on d->rwlock was released before
incrementing the entry's refcount. Between the RDUNLOCK and the
HA_ATOMIC_INC, another thread could call dict_entry_unref() to drop
the refcount to zero, acquire the write lock, delete the entry from
the tree, and free it. The subsequent HA_ATOMIC_INC would then be a
use-after-free on freed memory.
The fix moves the HA_ATOMIC_INC inside the read lock, matching the
pattern used in stick_table.c for identical refcount-then-unlock
sequences.
It can be backported to the branches where this is relevant.
HA_RWLOCK_RDLOCK(DICT_LOCK, &d->rwlock);
de = __dict_lookup(d, s);
- HA_RWLOCK_RDUNLOCK(DICT_LOCK, &d->rwlock);
if (de) {
HA_ATOMIC_INC(&de->refcount);
+ HA_RWLOCK_RDUNLOCK(DICT_LOCK, &d->rwlock);
return de;
}
+ HA_RWLOCK_RDUNLOCK(DICT_LOCK, &d->rwlock);
de = new_dict_entry(s);
if (!de)