From 4ccdd65bf667447c37d256d6b299fc60cfd19f78 Mon Sep 17 00:00:00 2001 From: lihangyu <15605149486@163.com> Date: Mon, 1 Aug 2022 22:52:19 +0800 Subject: [PATCH] [Fix](array) fix mysql_row_buffer may use after free when reserve() delete original address in dynamic_mode (#11395) ``` if (!_dynamic_mode) { int8store(_len_pos, _pos - _len_pos - 8); _len_pos = nullptr; } ``` _len_pos may be pointed to the pos which already deleted in reserve, int8store will asign value to the freed address, and lead to use after free when build in ASAN.So I changed _len_pos to the offset of _buf --- be/src/util/mysql_row_buffer.cpp | 15 ++++++++------- be/src/util/mysql_row_buffer.h | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/be/src/util/mysql_row_buffer.cpp b/be/src/util/mysql_row_buffer.cpp index 33844d0d54..dce4a478b6 100644 --- a/be/src/util/mysql_row_buffer.cpp +++ b/be/src/util/mysql_row_buffer.cpp @@ -67,7 +67,7 @@ MysqlRowBuffer::MysqlRowBuffer() _buf(_default_buf), _buf_size(sizeof(_default_buf)), _dynamic_mode(0), - _len_pos(nullptr) {} + _len_pos(0) {} MysqlRowBuffer::~MysqlRowBuffer() { if (_buf != _default_buf) { @@ -79,7 +79,7 @@ void MysqlRowBuffer::open_dynamic_mode() { if (!_dynamic_mode) { *_pos++ = NEXT_EIGHT_BYTE; // write length when dynamic mode close - _len_pos = _pos; + _len_pos = (_pos - _buf); _pos = _pos + 8; } _dynamic_mode++; @@ -88,9 +88,10 @@ void MysqlRowBuffer::open_dynamic_mode() { void MysqlRowBuffer::close_dynamic_mode() { _dynamic_mode--; + // _buf + _len_pos is the position to write length if (!_dynamic_mode) { - int8store(_len_pos, _pos - _len_pos - 8); - _len_pos = nullptr; + int8store((_buf + _len_pos), _pos - (_buf + _len_pos) - 8); + _len_pos = 0; } } @@ -113,14 +114,14 @@ int MysqlRowBuffer::reserve(int64_t size) { LOG(ERROR) << "alloc memory failed. size = " << alloc_size; return -1; } - - memcpy(new_buf, _buf, _pos - _buf); + size_t offset = _pos - _buf; + memcpy(new_buf, _buf, offset); if (_buf != _default_buf) { delete[] _buf; } - _pos = new_buf + (_pos - _buf); + _pos = new_buf + offset; _buf = new_buf; _buf_size = alloc_size; diff --git a/be/src/util/mysql_row_buffer.h b/be/src/util/mysql_row_buffer.h index 5d00ae9f68..54dc05bec6 100644 --- a/be/src/util/mysql_row_buffer.h +++ b/be/src/util/mysql_row_buffer.h @@ -124,7 +124,7 @@ private: char _default_buf[4096]; int _dynamic_mode; - char* _len_pos; + uint64_t _len_pos; }; } // namespace doris