[MDEV-17400] The result of TIME('42949672965959-01') depends on architecture Created: 2018-10-09  Updated: 2018-10-09  Resolved: 2018-10-09

Status: Closed
Project: MariaDB Server
Component/s: Data types, Temporal Types
Affects Version/s: 5.5, 10.0, 10.1, 10.2, 10.3, 10.4
Fix Version/s: 10.4.0

Type: Bug Priority: Major
Reporter: Alexander Barkov Assignee: Alexander Barkov
Resolution: Fixed Votes: 0
Labels: None

Issue Links:
Blocks
blocks MDEV-16991 Rounding vs truncation for TIME, DATE... Closed

 Description   

The code in str_to_time() in sql-common/my_time.c is not portable.
It can return different results on different architectures.

Platforms with sizeof(ulong)==4 (e.g. Linux 32bit, Windows)

SELECT TIME('42949672955959-01'), TIME('42949672965959-01');

+---------------------------+---------------------------+
| TIME('42949672955959-01') | TIME('42949672965959-01') |
+---------------------------+---------------------------+
| 838:59:59                 | 00:59:59                  |
+---------------------------+---------------------------+
1 row in set, 2 warnings (0.001 sec)

The result for the second column is wrong.

Platforms with sizeof(ulong)==8 (e.g. Linux 64bit)

SELECT TIME('42949672955959-01'), TIME('42949672965959-01');

+---------------------------+---------------------------+
| TIME('42949672955959-01') | TIME('42949672965959-01') |
+---------------------------+---------------------------+
| 838:59:59                 | NULL                      |
+---------------------------+---------------------------+
1 row in set, 2 warnings (0.00 sec)

The result for the second column is correct.

The underlying code description

  else
  {
    /* String given as one number; assume HHMMSS format */
    date[0]= 0;
    date[1]= (ulong) (value/10000);     //This line is not portable
    date[2]= (ulong) (value/100 % 100);
    date[3]= (ulong) (value % 100);
    state=4;
    goto fractional;
  }

The difference happens in the line assigning date[1]. For TIME('42949672965959-01'), "value" is 4294967296595.

Assigning (4294967296595/10000) to data[1]:

  • makes 4294967296 on platforms with sizeof(ulong)=8
  • overflows to 0 on platforms with sizeof(ulong)=4

On 64bit platforms a similar problem is repeatable with TIME('18446744073709551616-01')

SELECT TIME('18446744073709551615-01'),  TIME('18446744073709551616-01');

+---------------------------------+---------------------------------+
| TIME('18446744073709551615-01') | TIME('18446744073709551616-01') |
+---------------------------------+---------------------------------+
| NULL                            | 00:00:00                        |
+---------------------------------+---------------------------------+

Notice, the value for the second column is wrong. The expected value is NULL.


Generated at Thu Feb 08 08:36:11 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.