Details
-
Bug
-
Status: Confirmed (View Workflow)
-
Minor
-
Resolution: Unresolved
-
10.11, 11.4, 11.8, 12.3, 13.1, 10.6.28
Description
EXPORT_SET(bits, on, off, separator, number_of_bits) clips number_of_bits to 64
when it is larger than 64 – 65, 1000 and 2^64-1 all give 64 items – except
when it is 2^32 or more, where it is first taken modulo 2^32:
SELECT EXPORT_SET(3,'foo','bar',',',65); -- 64 items (correct, clipped) |
SELECT EXPORT_SET(3,'foo','bar',',',4); -- 'foo,foo,bar,bar' |
SELECT EXPORT_SET(3,'foo','bar',',',4294967296); -- '' (2^32 -> 0 items) |
SELECT EXPORT_SET(3,'foo','bar',',',4294967300); -- 'foo,foo,bar,bar' (2^32 + 4 -> 4 items) |
SELECT EXPORT_SET(3,'foo','bar',',',-4294967294); -- 'foo,foo' (-> 2 items) |
The MySQL manual documents the clip ("number_of_bits is silently clipped to 64 if
larger than 64. It is treated as an unsigned integer, so a value of -1 is
effectively the same as 64."), and MariaDB follows it for every other value,
including 18446744073709551615 and -1. MySQL 26.10.0 returns 64 items for every
call above except the 4-bit one.
Where (main, 82964737): sql/item_strfunc.cc, Item_func_export_set::val_str(),
lines 4311-4313:
num_set_values = (uint) args[4]->val_int();
|
if (num_set_values > 64)
|
num_set_values=64;
|
The (uint) cast happens before the comparison with 64.
Not the same code path as MDEV-40971 / MDEV-40987 (JSON path indexes, PERIOD_ADD,
SUBSTRING_INDEX, ELT): this is the number_of_bits argument of EXPORT_SET, in Item_func_export_set::val_str() (sql/item_strfunc.cc);
a fix there does not change this one.
================================================================================
STEPS TO REPRODUCE
================================================================================
SELECT EXPORT_SET(3,'foo','bar',',',4294967296); -- 1 |
SELECT EXPORT_SET(3,'foo','bar',',',4294967300); -- 2 |
SELECT EXPORT_SET(3,'foo','bar',',',-4294967294); -- 3 |
SELECT LENGTH(EXPORT_SET(3,'foo','bar',',',65)); -- 4 |
================================================================================
EXPECTED
================================================================================
1. 'foo,foo,bar,bar,...' (64 items, 255 characters)
|
2. same as 1
|
3. same as 1
|
4. 255
|
(MySQL 26.10.0 returns exactly this.)
================================================================================
ACTUAL (13.2.0 main 82964737; identical on 13.0.2, 11.8.9, 10.11.19, 10.6.28)
================================================================================
1. ''
|
2. 'foo,foo,bar,bar'
|
3. 'foo,foo'
|
4. 255
|
No warnings.
================================================================================
SUGGESTED FIX
================================================================================
Clip before narrowing, treating the argument as unsigned as documented:
ulonglong n= (ulonglong) args[4]->val_int();
|
num_set_values= n > 64 ? 64 : (uint) n;
|
================================================================================
ATTACHMENTS
================================================================================
repro.py (pymysql; exits 1 while the recorded wrong answers are returned).
VERIFY-main-82964737-2026-10-14.txt: transcript on main and the four release images.
Attachments
Issue Links
- relates to
-
MDEV-40971 JSON Path Array Index 32-bit Integer Truncation Wraparound ( [ 2 3 2 + n ] ≡ [2 3 2+n]≡[n])
-
- Confirmed
-