ClickHouse crushed on request to system.tables if has an incorrect "self-flushing" buffer table.

```
xxxx :) CREATE TABLE test (key UInt32) Engine=Buffer(default, test, 16, 10, 100, 10000, 1000000, 10000000, 100000000);


CREATE TABLE test
(
    `key` UInt32
)
ENGINE = Buffer(default, test, 16, 10, 100, 10000, 1000000, 10000000, 100000000)

Query id: a90ea965-ac7c-420f-a947-f900b6b0d014

Ok.

0 rows in set. Elapsed: 0.005 sec. 

xxxx :) select * from system.tables

SELECT *
FROM system.tables

Query id: bbb7d7eb-b782-4527-9803-ddc4f8703d5c

[xxxx] 2022.08.25 21:44:05.507879 [ 841325 ] <Fatal> BaseDaemon: ########################################
[xxxx] 2022.08.25 21:44:05.508036 [ 841325 ] <Fatal> BaseDaemon: (version 22.8.2.11 (official build), build id: F509FE73D83F8136) (from thread 841253) (query_id: bbb7d7eb-b782-4527-9803-ddc4f8703d5c) (query: select * from system.tables) Received signal Segmentation fault (11)
[xxxx] 2022.08.25 21:44:05.508105 [ 841325 ] <Fatal> BaseDaemon: Address: 0x7f06c12f7ff8 Access: write. Attempted access has violated the permissions assigned to the memory area.
[xxxx] 2022.08.25 21:44:05.508141 [ 841325 ] <Fatal> BaseDaemon: Stack trace: 0xa480065
[xxxx] 2022.08.25 21:44:05.508200 [ 841325 ] <Fatal> BaseDaemon: 2. ? @ 0xa480065 in /usr/bin/clickhouse
[xxxx] 2022.08.25 21:44:05.697982 [ 841325 ] <Fatal> BaseDaemon: Integrity check of the executable successfully passed (checksum: 26BBB329434F6C45E2D0312BCEE49FC1)
↘ Progress: 0.00 rows, 0.00 B (0.00 rows/s., 0.00 B/s.)                                                                                                                                                   Exception on client:
Code: 32. DB::Exception: Attempt to read after eof: while receiving packet from localhost:9000. (ATTEMPT_TO_READ_AFTER_EOF)

Connecting to localhost:9000 as user default.
Code: 210. DB::NetException: Connection reset by peer, while writing to socket ([::1]:9000). (NETWORK_ERROR)

```

Found on version 22.3.9.19, reproduced also on 22.8.2.11

namespace DB
{
/** During insertion, buffers the data in the RAM until certain thresholds are exceeded.
  * When thresholds are exceeded, flushes the data to another table.
  * When reading, it reads both from its buffers and from the subordinate table.
  *
  * The buffer is a set of num_shards blocks.
  * When writing, select the block number by the remainder of the `ThreadNumber` division by `num_shards` (or one of the others),
  *  and add rows to the corresponding block.
  * When using a block, it is locked by some mutex. If during write the corresponding block is already occupied
  *  - try to lock the next block in a round-robin fashion, and so no more than `num_shards` times (then wait for lock).
  * Thresholds are checked on insertion, and, periodically, in the background thread (to implement time thresholds).
  * Thresholds act independently for each shard. Each shard can be flushed independently of the others.
  * If a block is inserted into the table, which itself exceeds the max-thresholds, it is written directly to the subordinate table without buffering.
  * Thresholds can be exceeded. For example, if max_rows = 1 000 000, the buffer already had 500 000 rows,
  *  and a part of 800 000 rows is added, then there will be 1 300 000 rows in the buffer, and then such a block will be written to the subordinate table.
  *
  * There are also separate thresholds for flush, those thresholds are checked only for non-direct flush.
  * This maybe useful if you do not want to add extra latency for INSERT queries,
  * so you can set max_rows=1e6 and flush_rows=500e3, then each 500e3 rows buffer will be flushed in background only.
  *
  * When you destroy a Buffer table, all remaining data is flushed to the subordinate table.
  * The data in the buffer is not replicated, not logged to disk, not indexed. With a rough restart of the server, the data is lost.
  */
class StorageBuffer final : public IStorage, WithContext