mirror of
				https://github.com/MariaDB/server.git
				synced 2025-11-03 14:33:32 +03:00 
			
		
		
		
	The CONVERT_TZ function crashes the server when the timezone argument is an empty SET field value. 1) The CONVERT_TZ may find a timezone string in the tz_names hash. 2) A string representation of the empty SET is a String of zero length with the NULL pointer. 3) If the key argument length is zero, hash functions do comparison using the length of the record being compared against. I.e. a zero-length String buffer is an invalid argument for hash search functions, and if String points to NULL buffer, hashcmp() fails with SEGV accessing that memory. The my_tz_find function has been modified to treat empty Strings as invalid timezone values to skip unnecessary hash search.
		
			
				
	
	
		
			312 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			312 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
drop table if exists t1, t2;
 | 
						|
drop function if exists f1;
 | 
						|
create table t1 (ts timestamp);
 | 
						|
set time_zone='+00:00';
 | 
						|
select unix_timestamp(utc_timestamp())-unix_timestamp(current_timestamp());
 | 
						|
unix_timestamp(utc_timestamp())-unix_timestamp(current_timestamp())
 | 
						|
0
 | 
						|
insert into t1 (ts) values ('2003-03-30 02:30:00');
 | 
						|
set time_zone='+10:30';
 | 
						|
select unix_timestamp(utc_timestamp())-unix_timestamp(current_timestamp());
 | 
						|
unix_timestamp(utc_timestamp())-unix_timestamp(current_timestamp())
 | 
						|
-37800
 | 
						|
insert into t1 (ts) values ('2003-03-30 02:30:00');
 | 
						|
set time_zone='-10:00';
 | 
						|
select unix_timestamp(utc_timestamp())-unix_timestamp(current_timestamp());
 | 
						|
unix_timestamp(utc_timestamp())-unix_timestamp(current_timestamp())
 | 
						|
36000
 | 
						|
insert into t1 (ts) values ('2003-03-30 02:30:00');
 | 
						|
select * from t1;
 | 
						|
ts
 | 
						|
2003-03-29 16:30:00
 | 
						|
2003-03-29 06:00:00
 | 
						|
2003-03-30 02:30:00
 | 
						|
drop table t1;
 | 
						|
select Name from mysql.time_zone_name where Name in 
 | 
						|
('UTC','Universal','MET','Europe/Moscow','leap/Europe/Moscow');
 | 
						|
Name
 | 
						|
Europe/Moscow
 | 
						|
leap/Europe/Moscow
 | 
						|
MET
 | 
						|
Universal
 | 
						|
UTC
 | 
						|
create table t1 (i int, ts timestamp);
 | 
						|
set time_zone='MET';
 | 
						|
insert into t1 (i, ts) values
 | 
						|
(unix_timestamp('2003-03-01 00:00:00'),'2003-03-01 00:00:00');
 | 
						|
insert into t1 (i, ts) values
 | 
						|
(unix_timestamp('2003-03-30 01:59:59'),'2003-03-30 01:59:59'),
 | 
						|
(unix_timestamp('2003-03-30 02:30:00'),'2003-03-30 02:30:00'),
 | 
						|
(unix_timestamp('2003-03-30 03:00:00'),'2003-03-30 03:00:00');
 | 
						|
Warnings:
 | 
						|
Warning	1299	Invalid TIMESTAMP value in column 'ts' at row 2
 | 
						|
insert into t1 (i, ts) values
 | 
						|
(unix_timestamp(20030330015959),20030330015959),
 | 
						|
(unix_timestamp(20030330023000),20030330023000),
 | 
						|
(unix_timestamp(20030330030000),20030330030000);
 | 
						|
Warnings:
 | 
						|
Warning	1299	Invalid TIMESTAMP value in column 'ts' at row 2
 | 
						|
insert into t1 (i, ts) values
 | 
						|
(unix_timestamp('2003-05-01 00:00:00'),'2003-05-01 00:00:00');
 | 
						|
insert into t1 (i, ts) values
 | 
						|
(unix_timestamp('2003-10-26 01:00:00'),'2003-10-26 01:00:00'),
 | 
						|
(unix_timestamp('2003-10-26 02:00:00'),'2003-10-26 02:00:00'),
 | 
						|
(unix_timestamp('2003-10-26 02:59:59'),'2003-10-26 02:59:59'),
 | 
						|
(unix_timestamp('2003-10-26 04:00:00'),'2003-10-26 04:00:00'),
 | 
						|
(unix_timestamp('2003-10-26 02:59:59'),'2003-10-26 02:59:59');
 | 
						|
set time_zone='UTC';
 | 
						|
select * from t1;
 | 
						|
i	ts
 | 
						|
1046473200	2003-02-28 23:00:00
 | 
						|
1048985999	2003-03-30 00:59:59
 | 
						|
1048986000	2003-03-30 01:00:00
 | 
						|
1048986000	2003-03-30 01:00:00
 | 
						|
1048985999	2003-03-30 00:59:59
 | 
						|
1048986000	2003-03-30 01:00:00
 | 
						|
1048986000	2003-03-30 01:00:00
 | 
						|
1051740000	2003-04-30 22:00:00
 | 
						|
1067122800	2003-10-25 23:00:00
 | 
						|
1067126400	2003-10-26 00:00:00
 | 
						|
1067129999	2003-10-26 00:59:59
 | 
						|
1067137200	2003-10-26 03:00:00
 | 
						|
1067129999	2003-10-26 00:59:59
 | 
						|
truncate table t1;
 | 
						|
set time_zone='Europe/Moscow';
 | 
						|
insert into t1 (i, ts) values
 | 
						|
(unix_timestamp('2004-01-01 00:00:00'),'2004-01-01 00:00:00'),
 | 
						|
(unix_timestamp('2004-03-28 02:30:00'),'2004-03-28 02:30:00'),
 | 
						|
(unix_timestamp('2004-08-01 00:00:00'),'2003-08-01 00:00:00'),
 | 
						|
(unix_timestamp('2004-10-31 02:30:00'),'2004-10-31 02:30:00');
 | 
						|
Warnings:
 | 
						|
Warning	1299	Invalid TIMESTAMP value in column 'ts' at row 2
 | 
						|
select * from t1;
 | 
						|
i	ts
 | 
						|
1072904400	2004-01-01 00:00:00
 | 
						|
1080428400	2004-03-28 03:00:00
 | 
						|
1091304000	2003-08-01 00:00:00
 | 
						|
1099175400	2004-10-31 02:30:00
 | 
						|
truncate table t1;
 | 
						|
set time_zone='leap/Europe/Moscow';
 | 
						|
insert into t1 (i, ts) values
 | 
						|
(unix_timestamp('2004-01-01 00:00:00'),'2004-01-01 00:00:00'),
 | 
						|
(unix_timestamp('2004-03-28 02:30:00'),'2004-03-28 02:30:00'),
 | 
						|
(unix_timestamp('2004-08-01 00:00:00'),'2003-08-01 00:00:00'),
 | 
						|
(unix_timestamp('2004-10-31 02:30:00'),'2004-10-31 02:30:00');
 | 
						|
Warnings:
 | 
						|
Warning	1299	Invalid TIMESTAMP value in column 'ts' at row 2
 | 
						|
select * from t1;
 | 
						|
i	ts
 | 
						|
1072904422	2004-01-01 00:00:00
 | 
						|
1080428422	2004-03-28 03:00:00
 | 
						|
1091304022	2003-08-01 00:00:00
 | 
						|
1099175422	2004-10-31 02:30:00
 | 
						|
truncate table t1;
 | 
						|
insert into t1 (i, ts) values
 | 
						|
(unix_timestamp('1981-07-01 03:59:59'),'1981-07-01 03:59:59'),
 | 
						|
(unix_timestamp('1981-07-01 04:00:00'),'1981-07-01 04:00:00');
 | 
						|
select * from t1;
 | 
						|
i	ts
 | 
						|
362793608	1981-07-01 03:59:59
 | 
						|
362793610	1981-07-01 04:00:00
 | 
						|
select from_unixtime(362793609);
 | 
						|
from_unixtime(362793609)
 | 
						|
1981-07-01 03:59:59
 | 
						|
drop table t1;
 | 
						|
create table t1 (ts timestamp);
 | 
						|
set time_zone='UTC';
 | 
						|
insert into t1 values ('0000-00-00 00:00:00'),('1969-12-31 23:59:59'),
 | 
						|
('1970-01-01 00:00:00'),('1970-01-01 00:00:01'),
 | 
						|
('2038-01-19 03:14:07'),('2038-01-19 03:14:08');
 | 
						|
Warnings:
 | 
						|
Warning	1264	Out of range value for column 'ts' at row 2
 | 
						|
Warning	1264	Out of range value for column 'ts' at row 3
 | 
						|
Warning	1264	Out of range value for column 'ts' at row 6
 | 
						|
select * from t1;
 | 
						|
ts
 | 
						|
0000-00-00 00:00:00
 | 
						|
0000-00-00 00:00:00
 | 
						|
0000-00-00 00:00:00
 | 
						|
1970-01-01 00:00:01
 | 
						|
2038-01-19 03:14:07
 | 
						|
0000-00-00 00:00:00
 | 
						|
truncate table t1;
 | 
						|
set time_zone='MET';
 | 
						|
insert into t1 values ('0000-00-00 00:00:00'),('1970-01-01 00:30:00'),
 | 
						|
('1970-01-01 01:00:00'),('1970-01-01 01:00:01'),
 | 
						|
('2038-01-19 04:14:07'),('2038-01-19 04:14:08');
 | 
						|
Warnings:
 | 
						|
Warning	1264	Out of range value for column 'ts' at row 2
 | 
						|
Warning	1264	Out of range value for column 'ts' at row 3
 | 
						|
Warning	1264	Out of range value for column 'ts' at row 6
 | 
						|
select * from t1;
 | 
						|
ts
 | 
						|
0000-00-00 00:00:00
 | 
						|
0000-00-00 00:00:00
 | 
						|
0000-00-00 00:00:00
 | 
						|
1970-01-01 01:00:01
 | 
						|
2038-01-19 04:14:07
 | 
						|
0000-00-00 00:00:00
 | 
						|
truncate table t1;
 | 
						|
set time_zone='+01:30';
 | 
						|
insert into t1 values ('0000-00-00 00:00:00'),('1970-01-01 01:00:00'),
 | 
						|
('1970-01-01 01:30:00'),('1970-01-01 01:30:01'),
 | 
						|
('2038-01-19 04:44:07'),('2038-01-19 04:44:08');
 | 
						|
Warnings:
 | 
						|
Warning	1264	Out of range value for column 'ts' at row 2
 | 
						|
Warning	1264	Out of range value for column 'ts' at row 3
 | 
						|
Warning	1264	Out of range value for column 'ts' at row 6
 | 
						|
select * from t1;
 | 
						|
ts
 | 
						|
0000-00-00 00:00:00
 | 
						|
0000-00-00 00:00:00
 | 
						|
0000-00-00 00:00:00
 | 
						|
1970-01-01 01:30:01
 | 
						|
2038-01-19 04:44:07
 | 
						|
0000-00-00 00:00:00
 | 
						|
drop table t1;
 | 
						|
show variables like 'time_zone';
 | 
						|
Variable_name	Value
 | 
						|
time_zone	+01:30
 | 
						|
set time_zone = default;
 | 
						|
show variables like 'time_zone';
 | 
						|
Variable_name	Value
 | 
						|
time_zone	SYSTEM
 | 
						|
set time_zone= '0';
 | 
						|
ERROR HY000: Unknown or incorrect time zone: '0'
 | 
						|
set time_zone= '0:0';
 | 
						|
ERROR HY000: Unknown or incorrect time zone: '0:0'
 | 
						|
set time_zone= '-20:00';
 | 
						|
ERROR HY000: Unknown or incorrect time zone: '-20:00'
 | 
						|
set time_zone= '+20:00';
 | 
						|
ERROR HY000: Unknown or incorrect time zone: '+20:00'
 | 
						|
set time_zone= 'Some/Unknown/Time/Zone';
 | 
						|
ERROR HY000: Unknown or incorrect time zone: 'Some/Unknown/Time/Zone'
 | 
						|
select convert_tz(now(),'UTC', 'Universal') = now();
 | 
						|
convert_tz(now(),'UTC', 'Universal') = now()
 | 
						|
1
 | 
						|
select convert_tz(now(),'utc', 'UTC') = now();
 | 
						|
convert_tz(now(),'utc', 'UTC') = now()
 | 
						|
1
 | 
						|
select convert_tz('1917-11-07 12:00:00', 'MET', 'UTC');
 | 
						|
convert_tz('1917-11-07 12:00:00', 'MET', 'UTC')
 | 
						|
1917-11-07 12:00:00
 | 
						|
select convert_tz('1970-01-01 01:00:00', 'MET', 'UTC');
 | 
						|
convert_tz('1970-01-01 01:00:00', 'MET', 'UTC')
 | 
						|
1970-01-01 01:00:00
 | 
						|
select convert_tz('1970-01-01 01:00:01', 'MET', 'UTC');
 | 
						|
convert_tz('1970-01-01 01:00:01', 'MET', 'UTC')
 | 
						|
1970-01-01 00:00:01
 | 
						|
select convert_tz('2003-03-01 00:00:00', 'MET', 'UTC');
 | 
						|
convert_tz('2003-03-01 00:00:00', 'MET', 'UTC')
 | 
						|
2003-02-28 23:00:00
 | 
						|
select convert_tz('2003-03-30 01:59:59', 'MET', 'UTC');
 | 
						|
convert_tz('2003-03-30 01:59:59', 'MET', 'UTC')
 | 
						|
2003-03-30 00:59:59
 | 
						|
select convert_tz('2003-03-30 02:30:00', 'MET', 'UTC');
 | 
						|
convert_tz('2003-03-30 02:30:00', 'MET', 'UTC')
 | 
						|
2003-03-30 01:00:00
 | 
						|
select convert_tz('2003-03-30 03:00:00', 'MET', 'UTC');
 | 
						|
convert_tz('2003-03-30 03:00:00', 'MET', 'UTC')
 | 
						|
2003-03-30 01:00:00
 | 
						|
select convert_tz('2003-05-01 00:00:00', 'MET', 'UTC');
 | 
						|
convert_tz('2003-05-01 00:00:00', 'MET', 'UTC')
 | 
						|
2003-04-30 22:00:00
 | 
						|
select convert_tz('2003-10-26 01:00:00', 'MET', 'UTC');
 | 
						|
convert_tz('2003-10-26 01:00:00', 'MET', 'UTC')
 | 
						|
2003-10-25 23:00:00
 | 
						|
select convert_tz('2003-10-26 02:00:00', 'MET', 'UTC');
 | 
						|
convert_tz('2003-10-26 02:00:00', 'MET', 'UTC')
 | 
						|
2003-10-26 00:00:00
 | 
						|
select convert_tz('2003-10-26 02:59:59', 'MET', 'UTC');
 | 
						|
convert_tz('2003-10-26 02:59:59', 'MET', 'UTC')
 | 
						|
2003-10-26 00:59:59
 | 
						|
select convert_tz('2003-10-26 04:00:00', 'MET', 'UTC');
 | 
						|
convert_tz('2003-10-26 04:00:00', 'MET', 'UTC')
 | 
						|
2003-10-26 03:00:00
 | 
						|
select convert_tz('2038-01-19 04:14:07', 'MET', 'UTC');
 | 
						|
convert_tz('2038-01-19 04:14:07', 'MET', 'UTC')
 | 
						|
2038-01-19 03:14:07
 | 
						|
select convert_tz('2038-01-19 04:14:08', 'MET', 'UTC');
 | 
						|
convert_tz('2038-01-19 04:14:08', 'MET', 'UTC')
 | 
						|
2038-01-19 04:14:08
 | 
						|
select convert_tz('2103-01-01 04:00:00', 'MET', 'UTC');
 | 
						|
convert_tz('2103-01-01 04:00:00', 'MET', 'UTC')
 | 
						|
2103-01-01 04:00:00
 | 
						|
create table t1 (tz varchar(3));
 | 
						|
insert into t1 (tz) values ('MET'), ('UTC');
 | 
						|
select tz, convert_tz('2003-12-31 00:00:00',tz,'UTC'), convert_tz('2003-12-31 00:00:00','UTC',tz) from t1 order by tz;
 | 
						|
tz	convert_tz('2003-12-31 00:00:00',tz,'UTC')	convert_tz('2003-12-31 00:00:00','UTC',tz)
 | 
						|
MET	2003-12-30 23:00:00	2003-12-31 01:00:00
 | 
						|
UTC	2003-12-31 00:00:00	2003-12-31 00:00:00
 | 
						|
drop table t1;
 | 
						|
select convert_tz('2003-12-31 04:00:00', NULL, 'UTC');
 | 
						|
convert_tz('2003-12-31 04:00:00', NULL, 'UTC')
 | 
						|
NULL
 | 
						|
select convert_tz('2003-12-31 04:00:00', 'SomeNotExistingTimeZone', 'UTC');
 | 
						|
convert_tz('2003-12-31 04:00:00', 'SomeNotExistingTimeZone', 'UTC')
 | 
						|
NULL
 | 
						|
select convert_tz('2003-12-31 04:00:00', 'MET', 'SomeNotExistingTimeZone');
 | 
						|
convert_tz('2003-12-31 04:00:00', 'MET', 'SomeNotExistingTimeZone')
 | 
						|
NULL
 | 
						|
select convert_tz('2003-12-31 04:00:00', 'MET', NULL);
 | 
						|
convert_tz('2003-12-31 04:00:00', 'MET', NULL)
 | 
						|
NULL
 | 
						|
select convert_tz( NULL, 'MET', 'UTC');
 | 
						|
convert_tz( NULL, 'MET', 'UTC')
 | 
						|
NULL
 | 
						|
create table t1 (ts timestamp);
 | 
						|
set timestamp=1000000000;
 | 
						|
insert into t1 (ts) values (now());
 | 
						|
select convert_tz(ts, @@time_zone, 'Japan') from t1;
 | 
						|
convert_tz(ts, @@time_zone, 'Japan')
 | 
						|
2001-09-09 10:46:40
 | 
						|
drop table t1;
 | 
						|
select convert_tz('2005-01-14 17:00:00', 'UTC', custTimeZone) from (select 'UTC' as custTimeZone) as tmp;
 | 
						|
convert_tz('2005-01-14 17:00:00', 'UTC', custTimeZone)
 | 
						|
2005-01-14 17:00:00
 | 
						|
create table t1 select convert_tz(NULL, NULL, NULL);
 | 
						|
select * from t1;
 | 
						|
convert_tz(NULL, NULL, NULL)
 | 
						|
NULL
 | 
						|
drop table t1;
 | 
						|
SET @old_log_bin_trust_function_creators = @@global.log_bin_trust_function_creators;
 | 
						|
SET GLOBAL log_bin_trust_function_creators = 1;
 | 
						|
create table t1 (ldt datetime, udt datetime);
 | 
						|
create function f1(i datetime) returns datetime
 | 
						|
return convert_tz(i, 'UTC', 'Europe/Moscow');
 | 
						|
create trigger t1_bi before insert on t1 for each row
 | 
						|
set new.udt:= convert_tz(new.ldt, 'Europe/Moscow', 'UTC');
 | 
						|
insert into t1 (ldt) values ('2006-04-19 16:30:00');
 | 
						|
select * from t1;
 | 
						|
ldt	udt
 | 
						|
2006-04-19 16:30:00	2006-04-19 12:30:00
 | 
						|
select ldt, f1(udt) as ldt2 from t1;
 | 
						|
ldt	ldt2
 | 
						|
2006-04-19 16:30:00	2006-04-19 16:30:00
 | 
						|
drop table t1;
 | 
						|
drop function f1;
 | 
						|
SET @@global.log_bin_trust_function_creators= @old_log_bin_trust_function_creators;
 | 
						|
DROP TABLE IF EXISTS t1;
 | 
						|
CREATE TABLE t1 (t TIMESTAMP);
 | 
						|
INSERT INTO t1 VALUES (NULL), (NULL);
 | 
						|
LOCK TABLES t1 WRITE;
 | 
						|
SELECT CONVERT_TZ(NOW(), 'UTC', 'Europe/Moscow') IS NULL;
 | 
						|
CONVERT_TZ(NOW(), 'UTC', 'Europe/Moscow') IS NULL
 | 
						|
0
 | 
						|
UPDATE t1 SET t = CONVERT_TZ(t, 'UTC', 'Europe/Moscow');
 | 
						|
UNLOCK TABLES;
 | 
						|
DROP TABLE t1;
 | 
						|
#
 | 
						|
# Bug #55424: convert_tz crashes when fed invalid data
 | 
						|
#
 | 
						|
CREATE TABLE t1 (a SET('x') NOT NULL);
 | 
						|
INSERT INTO t1 VALUES ('');
 | 
						|
SELECT CONVERT_TZ(1, a, 1) FROM t1;
 | 
						|
CONVERT_TZ(1, a, 1)
 | 
						|
NULL
 | 
						|
SELECT CONVERT_TZ(1, 1, a) FROM t1;
 | 
						|
CONVERT_TZ(1, 1, a)
 | 
						|
NULL
 | 
						|
DROP TABLE t1;
 | 
						|
End of 5.1 tests
 |