Bug #119654 assert fail at mach_write_to_2 with a value larger than 0xFFFF.
Submitted: 9 Jan 10:01
Reporter: WANG jiaming Email Updates:
Status: Open Impact on me:
None 
Category:MySQL Server: InnoDB storage engine Severity:S2 (Serious)
Version:8.x OS:Linux
Assigned to: CPU Architecture:Any
Tags: clone plugin, innodb assertion crash

[9 Jan 10:01] WANG jiaming
Description:
assert fail at mach_write_to_2 with a value larger than 0xFFFF.

Arch_Block::add_reset writing the block_num to the buf with:
```c++
...
mach_write_to_2(buf + m_data_len, reset_pos.m_block_num);
...
```
which writes a 8 bytes integer to a 2 bytes buffer. When the block_num is bigger than 0xFFFF, assert fail in mach_write_to_2. In release versions, there is no asserts which will cause data loss using clone plugin.

The block_num indicates the num of data blocks in current active page archiving group. When the block_num exceeds 0xFFFF which means we have 32 ib_page_# file in current group, the written block_num is wrong, and will be flushed to file later.

Later, any newly added reset points are with wrong block_num. When restarting the Server, recovering from the ib_page_# files with function: Arch_File_Ctx::parse_reset_points, the reset_lsn read according to the block_num saved could be LSN_MAX which is the default value for data blocks with no reset points. After that, the behaviour is undefined. The final consequence could be returning wrong tracked page ids and then data loss of cloning or failure of any other tools depend on page tracking system. In our system, lots of backup failures using clone and could have data loss and are abandoned.

I'm using MySQL 8.x, don't know if it exists in 9.x. Didn't find the bug in bug list, sorry if already fixed.

How to repeat:
Using debug version of MySQL
1. Start page tracking with function: select mysqlbackup_page_track_set(somelsn);
2. do lots of tests, until directory /data_dir/#ib_archive/page_group_####/ have 32 ib_page_# files. Here needs lots of page flush and page tracking reset points.
3. Continue to add more reset points, mysqld will crash at assert fail in function mach_write_to_2.

Suggested fix:
It seems that in function Arch_Block::add_reset, line:
mach_write_to_2(buf + m_data_len, reset_pos.m_block_num); 
should be changed to:
mach_write_to_2(buf + m_data_len, reset_pos.m_block_num % ARCH_PAGE_FILE_DATA_CAPACITY);

If different patch is used please let me know.