Description:
# `HEX()` metadata overflow truncates grouped results
## Summary
`HEX()` doubles its argument's declared maximum length with unchecked 32-bit
arithmetic. A legal expression descriptor just above `2^31` therefore wraps
to a tiny width. Direct evaluation returns the complete value, while a
temporary-table consumer such as `GROUP BY` silently truncates it.
This is a Release-build result-integrity bug. It does not require a large row,
large packet, malformed storage, or an extension. The reproducer stores one
byte and the server remains alive.
## Affected version
Reproduced twice on MySQL Community Server 8.4.10, both the official optimized
image and an exact-source Debug+ASan build. The same arithmetic is retained in
the checked MySQL 8.4.11 source revision.
## Reproduction
Run the file with a user that can create objects in a test schema:
```sh
mysql --force -uroot -p < reproduce.sql
```
The control and trigger differ only in the `SUBSTRING()` start position:
`2147483646` versus `2147483647`. Both select the same runtime value `AA`.
Expected observations:
- direct control and trigger both return `4141`;
- grouped control returns `4141`;
- grouped trigger returns only `41`;
- the control view declares four bytes, while the trigger view declares two.
How to repeat:
DROP DATABASE IF EXISTS h54;
CREATE DATABASE h54;
USE h54;
CREATE TABLE source_data(a LONGBLOB);
INSERT INTO source_data VALUES (_binary'A');
SELECT HEX(IF(a IS NOT NULL,_binary'AA',SUBSTRING(a,2147483646)))
AS control_direct
FROM source_data;
SELECT HEX(IF(a IS NOT NULL,_binary'AA',SUBSTRING(a,2147483647)))
AS trigger_direct
FROM source_data;
SELECT HEX(IF(a IS NOT NULL,_binary'AA',SUBSTRING(a,2147483646)))
AS control_grouped
FROM source_data GROUP BY control_grouped;
SELECT HEX(IF(a IS NOT NULL,_binary'AA',SUBSTRING(a,2147483647)))
AS trigger_grouped
FROM source_data GROUP BY trigger_grouped;
CREATE VIEW control_view AS
SELECT HEX(IF(a IS NOT NULL,_binary'AA',SUBSTRING(a,2147483646))) AS h
FROM source_data;
CREATE VIEW trigger_view AS
SELECT HEX(IF(a IS NOT NULL,_binary'AA',SUBSTRING(a,2147483647))) AS h
FROM source_data;
SELECT TABLE_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH
FROM information_schema.columns
WHERE TABLE_SCHEMA='h54' AND TABLE_NAME IN ('control_view','trigger_view')
ORDER BY TABLE_NAME;
Description: # `HEX()` metadata overflow truncates grouped results ## Summary `HEX()` doubles its argument's declared maximum length with unchecked 32-bit arithmetic. A legal expression descriptor just above `2^31` therefore wraps to a tiny width. Direct evaluation returns the complete value, while a temporary-table consumer such as `GROUP BY` silently truncates it. This is a Release-build result-integrity bug. It does not require a large row, large packet, malformed storage, or an extension. The reproducer stores one byte and the server remains alive. ## Affected version Reproduced twice on MySQL Community Server 8.4.10, both the official optimized image and an exact-source Debug+ASan build. The same arithmetic is retained in the checked MySQL 8.4.11 source revision. ## Reproduction Run the file with a user that can create objects in a test schema: ```sh mysql --force -uroot -p < reproduce.sql ``` The control and trigger differ only in the `SUBSTRING()` start position: `2147483646` versus `2147483647`. Both select the same runtime value `AA`. Expected observations: - direct control and trigger both return `4141`; - grouped control returns `4141`; - grouped trigger returns only `41`; - the control view declares four bytes, while the trigger view declares two. How to repeat: DROP DATABASE IF EXISTS h54; CREATE DATABASE h54; USE h54; CREATE TABLE source_data(a LONGBLOB); INSERT INTO source_data VALUES (_binary'A'); SELECT HEX(IF(a IS NOT NULL,_binary'AA',SUBSTRING(a,2147483646))) AS control_direct FROM source_data; SELECT HEX(IF(a IS NOT NULL,_binary'AA',SUBSTRING(a,2147483647))) AS trigger_direct FROM source_data; SELECT HEX(IF(a IS NOT NULL,_binary'AA',SUBSTRING(a,2147483646))) AS control_grouped FROM source_data GROUP BY control_grouped; SELECT HEX(IF(a IS NOT NULL,_binary'AA',SUBSTRING(a,2147483647))) AS trigger_grouped FROM source_data GROUP BY trigger_grouped; CREATE VIEW control_view AS SELECT HEX(IF(a IS NOT NULL,_binary'AA',SUBSTRING(a,2147483646))) AS h FROM source_data; CREATE VIEW trigger_view AS SELECT HEX(IF(a IS NOT NULL,_binary'AA',SUBSTRING(a,2147483647))) AS h FROM source_data; SELECT TABLE_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH FROM information_schema.columns WHERE TABLE_SCHEMA='h54' AND TABLE_NAME IN ('control_view','trigger_view') ORDER BY TABLE_NAME;