[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
This commit is contained in:
lihangyu
2022-08-01 22:52:19 +08:00
committed by GitHub
parent 667689e9ba
commit 4ccdd65bf6
2 changed files with 9 additions and 8 deletions

View File

@ -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;

View File

@ -124,7 +124,7 @@ private:
char _default_buf[4096];
int _dynamic_mode;
char* _len_pos;
uint64_t _len_pos;
};
} // namespace doris