Commit 45a87c68 authored by Gleb Shchepa's avatar Gleb Shchepa

Bug #55424: convert_tz crashes when fed invalid data

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.


mysql-test/r/timezone2.result:
  Test case for bug #55424.
mysql-test/t/timezone2.test:
  Test case for bug #55424.
sql/sql_string.h:
  Bug #55424: convert_tz crashes when fed invalid data
  
  Added "const" modifier to String::is_empty().
sql/tztime.cc:
  Bug #55424: convert_tz crashes when fed invalid data
  
  The my_tz_find function has been modified to
  treat empty Strings as invalid timezone values
  to skip unnecessary hash search.
parent 09eb23d5
...@@ -296,4 +296,16 @@ CONVERT_TZ(NOW(), 'UTC', 'Europe/Moscow') IS NULL ...@@ -296,4 +296,16 @@ CONVERT_TZ(NOW(), 'UTC', 'Europe/Moscow') IS NULL
UPDATE t1 SET t = CONVERT_TZ(t, 'UTC', 'Europe/Moscow'); UPDATE t1 SET t = CONVERT_TZ(t, 'UTC', 'Europe/Moscow');
UNLOCK TABLES; UNLOCK TABLES;
DROP TABLE t1; 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 End of 5.1 tests
...@@ -273,5 +273,14 @@ UNLOCK TABLES; ...@@ -273,5 +273,14 @@ UNLOCK TABLES;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # Bug #55424: convert_tz crashes when fed invalid data
--echo #
CREATE TABLE t1 (a SET('x') NOT NULL);
INSERT INTO t1 VALUES ('');
SELECT CONVERT_TZ(1, a, 1) FROM t1;
SELECT CONVERT_TZ(1, 1, a) FROM t1;
DROP TABLE t1;
--echo End of 5.1 tests --echo End of 5.1 tests
...@@ -97,7 +97,7 @@ class String ...@@ -97,7 +97,7 @@ class String
inline uint32 alloced_length() const { return Alloced_length;} inline uint32 alloced_length() const { return Alloced_length;}
inline char& operator [] (uint32 i) const { return Ptr[i]; } inline char& operator [] (uint32 i) const { return Ptr[i]; }
inline void length(uint32 len) { str_length=len ; } inline void length(uint32 len) { str_length=len ; }
inline bool is_empty() { return (str_length == 0); } inline bool is_empty() const { return (str_length == 0); }
inline void mark_as_const() { Alloced_length= 0;} inline void mark_as_const() { Alloced_length= 0;}
inline const char *ptr() const { return Ptr; } inline const char *ptr() const { return Ptr; }
inline char *c_ptr() inline char *c_ptr()
......
...@@ -2259,7 +2259,7 @@ my_tz_find(THD *thd, const String *name) ...@@ -2259,7 +2259,7 @@ my_tz_find(THD *thd, const String *name)
DBUG_PRINT("enter", ("time zone name='%s'", DBUG_PRINT("enter", ("time zone name='%s'",
name ? ((String *)name)->c_ptr_safe() : "NULL")); name ? ((String *)name)->c_ptr_safe() : "NULL"));
if (!name) if (!name || name->is_empty())
DBUG_RETURN(0); DBUG_RETURN(0);
VOID(pthread_mutex_lock(&tz_LOCK)); VOID(pthread_mutex_lock(&tz_LOCK));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment