Details
-
Bug
-
Status: Needs Feedback (View Workflow)
-
Major
-
Resolution: Unresolved
-
None
-
None
-
None
-
MariaDB source HEAD `c894d97781b5` (13.2.0-alpha)
Description
`buf_tmp_reserve_compression_buf()` (`storage/innobase/buf/buf0flu.cc:583-597`) lazily
allocates one `comp_buf` per I/O slot and never resizes it. Its size is chosen by the
current provider state only:
```c
ulint size = srv_page_size;
if (provider_service_lzo->is_loaded)
size = LZO1X_1_15_MEM_COMPRESS;
```
`LZO1X_1_15_MEM_COMPRESS` is `32768 * sizeof(uchar*)` = 262144 on LP64
(`include/providers/lzo/lzo1x.h:23`). However, the LZO compressor
(`storage/innobase/fil/fil0pagecompress.cc:101-112`) writes its output at
`out_buf + header_len` *and its work memory at `out_buf + srv_page_size`*:
```c
lzo1x_1_15_compress(buf, srv_page_size, out_buf + header_len, &len,
out_buf + srv_page_size);
```
The required allocation is therefore `srv_page_size + LZO1X_1_15_MEM_COMPRESS`, not
`LZO1X_1_15_MEM_COMPRESS`. The pre-2022 code computed exactly that
(`size = size + LZO1X_1_15_MEM_COMPRESS`); the 2022 merge `8ebff3bcb02e` resolved the
conflict by replacing it with `size = LZO1X_1_15_MEM_COMPRESS`, dropping the
`+ srv_page_size` part. As a result every LZO page compression writes
`srv_page_size` bytes past the end of the buffer (and if the slot was first sized while
`provider_lzo` was not yet loaded, it is only `srv_page_size` long, so the whole 256 KiB
work-memory area lands past the end).
-
- Steps to reproduce
Configuration needed (all admin-controlled):
1. `provider_lzo` loaded (`--plugin-load-add=provider_lzo` or `INSTALL SONAME`), with
`innodb_compression_algorithm=lzo`; or have the slot allocated before the provider is
loaded (late `INSTALL SONAME provider_lzo`).
2. A table in a `PAGE_COMPRESSED=1` tablespace.
3. Any operation that flushes a compressed page (DML, checkpoint, shutdown).
Then the LZO compression path runs with the undersized `comp_buf`. A build with ASAN or
a guarded allocator should report a heap-buffer-overflow write of up to `srv_page_size`
bytes; without instrumentation the corruption may stay silent for a while.
-
- Expected result
`comp_buf` must be sized for the full LZO requirement
(`srv_page_size + LZO1X_1_15_MEM_COMPRESS`) and re-validated if the provider state
changes after the first allocation. The pre-merge arithmetic documents the intended
contract.