Prevent misaligned read from common::container::ring_buffer (#1076)

- causes undefined behavior
Cette révision appartient à :
Jonathan R. Madsen
2024-09-12 18:25:05 -05:00
révisé par GitHub
Parent 8c1382fceb
révision 6098d52335
2 fichiers modifiés avec 24 ajouts et 12 suppressions
+8 -4
Voir le fichier
@@ -138,7 +138,7 @@ ring_buffer::request(size_t _length, size_t _align, bool _wrap)
{
if(m_ptr == nullptr || m_size == 0) return nullptr;
if(is_full()) return (_wrap) ? retrieve(_length) : nullptr;
if(is_full()) return (_wrap) ? retrieve(_length, _align) : nullptr;
LOG_IF(FATAL, _align == 0) << "alignment must be non-zero";
@@ -169,7 +169,7 @@ ring_buffer::request(size_t _length, size_t _align, bool _wrap)
//
void*
ring_buffer::retrieve(size_t _length) const
ring_buffer::retrieve(size_t _length, size_t _align) const
{
if(m_ptr == nullptr || m_size == 0) return nullptr;
@@ -179,6 +179,7 @@ ring_buffer::retrieve(size_t _length) const
// if read count is at the tail of buffer, bump to the end of buffer
size_t _read_count = 0;
size_t _offset = 0;
size_t _read_pos = 0;
do
{
if(_length > count()) return nullptr;
@@ -186,11 +187,14 @@ ring_buffer::retrieve(size_t _length) const
_read_count = m_read_count.load(std::memory_order_acquire);
auto _modulo = m_size - (_read_count % m_size);
if(_modulo < _length) _offset = _modulo;
auto _align_modulo = (_read_count % _align);
auto _align_offset = (_align_modulo > 0) ? (_align - _align_modulo) : 0;
_read_pos = _read_count + _align_offset;
} while(!m_read_count.compare_exchange_strong(
_read_count, _read_count + _length + _offset, std::memory_order_seq_cst));
_read_count, _read_pos + _length + _offset, std::memory_order_seq_cst));
// pointer in buffer
void* _out = read_ptr(_read_count);
void* _out = read_ptr(_read_pos);
return _out;
}