Details
-
Bug
-
Status: Open (View Workflow)
-
Minor
-
Resolution: Unresolved
-
10.11
-
None
Description
INTERVAL::year and INTERVAL::month are unsigned, but date_add_interval() (sql/sql_time.cc) casts them to long and does signed arithmetic before the range check:
case INTERVAL_YEAR: |
ltime->year+= sign * (long) interval.year; |
...
|
case INTERVAL_MONTH: |
long period= (ltime->year*12 + sign * (long) interval.year*12 + |
ltime->month-1 + sign * (long) interval.month); |
With values above LONG_MAX (or LONG_MAX/12 for years) the cast is implementation-defined and the multiplication/addition is signed overflow, which is undefined behaviour.
In practice the current builds still end in a clean error, so this is not a visible wrong result today; UBSAN should flag it:
select date_add('2000-01-01', interval 9223372036854775808 month), |
date_add('2000-01-01', interval 768614336404564651 year); |
-- NULL, NULL, Warning 1441 Datetime function: datetime field overflow
|
 |
create table t1 (x int) with system versioning |
partition by system_time interval 9223372036854775808 month; |
-- ERROR 1690 TIMESTAMP value is out of range in 'INTERVAL'
|
Expected: check the year/month magnitude (as is already done for days with MAX_DAY_NUMBER) before the arithmetic.
Present in 10.11 and later.
Found during review of MDEV-25529 (https://github.com/MariaDB/server/pull/5294); the code predates that change.
Attachments
Issue Links
- relates to
-
MDEV-25529 Auto-create: Pre-existing historical data is not partitioned as specified by ALTER
-
- In Testing
-