Commit 17994c9e authored by zbdba's avatar zbdba Committed by Daniel Black

MDEV-23299: Bad data in mysql.func can cause crash

udf_init() can crash when the name field is empty.

We correct this by applying CHECK column constraints on
columns in the mysql.func tables.

The constrains are as follows:
* name cannot be an empty string;
* ret, the return type can be;
  * STRING_RESULT(0),
  * REAL_RESULT(1),
  * INT_RESULT(2),
  * and DECIMAL_RESULT(4);
  * but not ROW_RESULT(3) or TIME_RESULT(5).
*  dl, cannot be empty string

Upgrades ensure that any invalid functions are deleted.

closes #1643
parent f99de891
......@@ -36,3 +36,16 @@ DROP FUNCTION metaphon;
DROP FUNCTION IF EXISTS metaphon;
Warnings:
Note 1305 FUNCTION test.metaphon does not exist
#
# MDEV-23299 The udf_init() function cause server crash.
#
INSERT into mysql.func(name, ret, dl) values('example', 0, 'example.so');
INSERT into mysql.func(ret) values(0);
ERROR HY000: Field 'name' doesn't have a default value
INSERT into mysql.func(name, ret, dl) values('', 0, 'example.so');
ERROR 23000: CONSTRAINT `func.name` failed for `mysql`.`func`
INSERT into mysql.func(name, ret, dl) values('example', 6, 'example.so');
ERROR 23000: CONSTRAINT `func.ret` failed for `mysql`.`func`
INSERT into mysql.func(name, ret, dl) values('example', 0, '');
ERROR 23000: CONSTRAINT `func.dl` failed for `mysql`.`func`
DELETE from mysql.func WHERE name='example';
......@@ -35,3 +35,22 @@ SELECT metaphon('mariadb');
DROP FUNCTION metaphon;
DROP FUNCTION IF EXISTS metaphon;
--echo #
--echo # MDEV-23299 The udf_init() function cause server crash.
--echo #
INSERT into mysql.func(name, ret, dl) values('example', 0, 'example.so');
--error ER_NO_DEFAULT_FOR_FIELD
INSERT into mysql.func(ret) values(0);
--error ER_CONSTRAINT_FAILED
INSERT into mysql.func(name, ret, dl) values('', 0, 'example.so');
--error ER_CONSTRAINT_FAILED
INSERT into mysql.func(name, ret, dl) values('example', 6, 'example.so');
--error ER_CONSTRAINT_FAILED
INSERT into mysql.func(name, ret, dl) values('example', 0, '');
DELETE from mysql.func WHERE name='example';
......@@ -66,9 +66,9 @@ user CREATE ALGORITHM=UNDEFINED DEFINER=`mariadb.sys`@`localhost` SQL SECURITY D
show create table func;
Table Create Table
func CREATE TABLE `func` (
`name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '',
`ret` tinyint(1) NOT NULL DEFAULT 0,
`dl` char(128) COLLATE utf8_bin NOT NULL DEFAULT '',
`name` char(64) COLLATE utf8_bin NOT NULL CHECK (`name` <> ''),
`ret` tinyint(1) NOT NULL DEFAULT 0 CHECK (`ret` <> 3 and `ret` between 0 and 4),
`dl` char(128) COLLATE utf8_bin NOT NULL CHECK (`dl` <> ''),
`type` enum('function','aggregate') CHARACTER SET utf8 NOT NULL,
PRIMARY KEY (`name`)
) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='User defined functions'
......
......@@ -104,9 +104,9 @@ user CREATE ALGORITHM=UNDEFINED DEFINER=`mariadb.sys`@`localhost` SQL SECURITY D
show create table func;
Table Create Table
func CREATE TABLE `func` (
`name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '',
`ret` tinyint(1) NOT NULL DEFAULT 0,
`dl` char(128) COLLATE utf8_bin NOT NULL DEFAULT '',
`name` char(64) COLLATE utf8_bin NOT NULL CHECK (`name` <> ''),
`ret` tinyint(1) NOT NULL DEFAULT 0 CHECK (`ret` <> 3 and `ret` between 0 and 4),
`dl` char(128) COLLATE utf8_bin NOT NULL CHECK (`dl` <> ''),
`type` enum('function','aggregate') CHARACTER SET utf8 NOT NULL,
PRIMARY KEY (`name`)
) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='User defined functions'
......
......@@ -108,9 +108,9 @@ user CREATE ALGORITHM=UNDEFINED DEFINER=`mariadb.sys`@`localhost` SQL SECURITY D
show create table func;
Table Create Table
func CREATE TABLE `func` (
`name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '',
`ret` tinyint(1) NOT NULL DEFAULT 0,
`dl` char(128) COLLATE utf8_bin NOT NULL DEFAULT '',
`name` char(64) COLLATE utf8_bin NOT NULL CHECK (`name` <> ''),
`ret` tinyint(1) NOT NULL DEFAULT 0 CHECK (`ret` <> 3 and `ret` between 0 and 4),
`dl` char(128) COLLATE utf8_bin NOT NULL CHECK (`dl` <> ''),
`type` enum('function','aggregate') CHARACTER SET utf8 NOT NULL,
PRIMARY KEY (`name`)
) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='User defined functions'
......
......@@ -88,9 +88,9 @@ user CREATE ALGORITHM=UNDEFINED DEFINER=`mariadb.sys`@`localhost` SQL SECURITY D
show create table func;
Table Create Table
func CREATE TABLE `func` (
`name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '',
`ret` tinyint(1) NOT NULL DEFAULT 0,
`dl` char(128) COLLATE utf8_bin NOT NULL DEFAULT '',
`name` char(64) COLLATE utf8_bin NOT NULL CHECK (`name` <> ''),
`ret` tinyint(1) NOT NULL DEFAULT 0 CHECK (`ret` <> 3 and `ret` between 0 and 4),
`dl` char(128) COLLATE utf8_bin NOT NULL CHECK (`dl` <> ''),
`type` enum('function','aggregate') CHARACTER SET utf8 NOT NULL,
PRIMARY KEY (`name`)
) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='User defined functions'
......
......@@ -7,7 +7,7 @@ delete from test_user;
insert ignore into test_user (Host,User) values (@name,@name);
create table test_func select * from mysql.func;
delete from test_func;
insert ignore into test_func (name) values (@name);
insert ignore into test_func (name, dl) values (@name, @name);
create table test_tables_priv select * from mysql.tables_priv;
delete from test_tables_priv;
insert ignore into test_tables_priv (Host,Db,User,Table_name) values (@name,@name,@name,@name);
......
......@@ -23,7 +23,7 @@ insert ignore into test_user (Host,User) values (@name,@name);
create table test_func select * from mysql.func;
delete from test_func;
--disable_warnings
insert ignore into test_func (name) values (@name);
insert ignore into test_func (name, dl) values (@name, @name);
--enable_warnings
create table test_tables_priv select * from mysql.tables_priv;
......
......@@ -135,6 +135,9 @@ GRANT SELECT (a) ON `db`.`t1` TO `foo`@`%`
SELECT * FROM information_schema.check_constraints;
CONSTRAINT_CATALOG CONSTRAINT_SCHEMA TABLE_NAME CONSTRAINT_NAME CHECK_CLAUSE
def db t1 CONSTRAINT_1 `b` > 0
def mysql func dl `dl` <> ''
def mysql func name `name` <> ''
def mysql func ret `ret` <> 3 and `ret` between 0 and 4
def mysql global_priv Priv json_valid(`Priv`)
CONNECT con1,localhost, foo,, db;
SELECT a FROM t1;
......
......@@ -65,8 +65,8 @@ def mysql event sql_mode 15 '' NO set 561 1683 NULL NULL NULL utf8 utf8_general_
def mysql event starts 11 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select,insert,update,references NEVER NULL
def mysql event status 13 'ENABLED' NO enum 18 54 NULL NULL NULL utf8 utf8_general_ci enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') select,insert,update,references NEVER NULL
def mysql event time_zone 18 'SYSTEM' NO char 64 64 NULL NULL NULL latin1 latin1_swedish_ci char(64) select,insert,update,references NEVER NULL
def mysql func dl 3 '' NO char 128 384 NULL NULL NULL utf8 utf8_bin char(128) select,insert,update,references NEVER NULL
def mysql func name 1 '' NO char 64 192 NULL NULL NULL utf8 utf8_bin char(64) PRI select,insert,update,references NEVER NULL
def mysql func dl 3 NULL NO char 128 384 NULL NULL NULL utf8 utf8_bin char(128) select,insert,update,references NEVER NULL
def mysql func name 1 NULL NO char 64 192 NULL NULL NULL utf8 utf8_bin char(64) PRI select,insert,update,references NEVER NULL
def mysql func ret 2 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(1) select,insert,update,references NEVER NULL
def mysql func type 4 NULL NO enum 9 27 NULL NULL NULL utf8 utf8_general_ci enum('function','aggregate') select,insert,update,references NEVER NULL
def mysql general_log argument 6 NULL NO mediumtext 16777215 16777215 NULL NULL NULL utf8 utf8_general_ci mediumtext select,insert,update,references NEVER NULL
......
......@@ -65,8 +65,8 @@ def mysql event sql_mode 15 '' NO set 561 1683 NULL NULL NULL utf8 utf8_general_
def mysql event starts 11 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL
def mysql event status 13 'ENABLED' NO enum 18 54 NULL NULL NULL utf8 utf8_general_ci enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') NEVER NULL
def mysql event time_zone 18 'SYSTEM' NO char 64 64 NULL NULL NULL latin1 latin1_swedish_ci char(64) NEVER NULL
def mysql func dl 3 '' NO char 128 384 NULL NULL NULL utf8 utf8_bin char(128) NEVER NULL
def mysql func name 1 '' NO char 64 192 NULL NULL NULL utf8 utf8_bin char(64) PRI NEVER NULL
def mysql func dl 3 NULL NO char 128 384 NULL NULL NULL utf8 utf8_bin char(128) NEVER NULL
def mysql func name 1 NULL NO char 64 192 NULL NULL NULL utf8 utf8_bin char(64) PRI NEVER NULL
def mysql func ret 2 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(1) NEVER NULL
def mysql func type 4 NULL NO enum 9 27 NULL NULL NULL utf8 utf8_general_ci enum('function','aggregate') NEVER NULL
def mysql general_log argument 6 NULL NO mediumtext 16777215 16777215 NULL NULL NULL utf8 utf8_general_ci mediumtext NEVER NULL
......
......@@ -62,7 +62,10 @@ def mysql PRIMARY mysql columns_priv
def mysql PRIMARY mysql column_stats
def mysql PRIMARY mysql db
def mysql PRIMARY mysql event
def mysql dl mysql func
def mysql name mysql func
def mysql PRIMARY mysql func
def mysql ret mysql func
def mysql PRIMARY mysql global_priv
def mysql Priv mysql global_priv
def mysql PRIMARY mysql gtid_slave_pos
......
......@@ -11,7 +11,10 @@ def mysql PRIMARY mysql columns_priv PRIMARY KEY
def mysql PRIMARY mysql column_stats PRIMARY KEY
def mysql PRIMARY mysql db PRIMARY KEY
def mysql PRIMARY mysql event PRIMARY KEY
def mysql dl mysql func CHECK
def mysql name mysql func CHECK
def mysql PRIMARY mysql func PRIMARY KEY
def mysql ret mysql func CHECK
def mysql PRIMARY mysql global_priv PRIMARY KEY
def mysql Priv mysql global_priv CHECK
def mysql PRIMARY mysql gtid_slave_pos PRIMARY KEY
......
......@@ -11,7 +11,10 @@ def mysql PRIMARY mysql columns_priv PRIMARY KEY
def mysql PRIMARY mysql column_stats PRIMARY KEY
def mysql PRIMARY mysql db PRIMARY KEY
def mysql PRIMARY mysql event PRIMARY KEY
def mysql dl mysql func CHECK
def mysql name mysql func CHECK
def mysql PRIMARY mysql func PRIMARY KEY
def mysql ret mysql func CHECK
def mysql PRIMARY mysql global_priv PRIMARY KEY
def mysql Priv mysql global_priv CHECK
def mysql PRIMARY mysql gtid_slave_pos PRIMARY KEY
......@@ -49,7 +52,10 @@ def mysql PRIMARY mysql columns_priv PRIMARY KEY
def mysql PRIMARY mysql column_stats PRIMARY KEY
def mysql PRIMARY mysql db PRIMARY KEY
def mysql PRIMARY mysql event PRIMARY KEY
def mysql dl mysql func CHECK
def mysql name mysql func CHECK
def mysql PRIMARY mysql func PRIMARY KEY
def mysql ret mysql func CHECK
def mysql PRIMARY mysql global_priv PRIMARY KEY
def mysql Priv mysql global_priv CHECK
def mysql PRIMARY mysql gtid_slave_pos PRIMARY KEY
......
......@@ -115,7 +115,7 @@ TABLE_SCHEMA mysql
TABLE_NAME func
TABLE_TYPE BASE TABLE
ENGINE MYISAM_OR_MARIA
VERSION 10
VERSION 11
ROW_FORMAT DYNAMIC_OR_PAGE
TABLE_ROWS #TBLR#
AVG_ROW_LENGTH #ARL#
......
......@@ -115,7 +115,7 @@ TABLE_SCHEMA mysql
TABLE_NAME func
TABLE_TYPE BASE TABLE
ENGINE MYISAM_OR_MARIA
VERSION 10
VERSION 11
ROW_FORMAT DYNAMIC_OR_PAGE
TABLE_ROWS #TBLR#
AVG_ROW_LENGTH #ARL#
......@@ -904,7 +904,7 @@ TABLE_SCHEMA mysql
TABLE_NAME func
TABLE_TYPE BASE TABLE
ENGINE MYISAM_OR_MARIA
VERSION 10
VERSION 11
ROW_FORMAT DYNAMIC_OR_PAGE
TABLE_ROWS #TBLR#
AVG_ROW_LENGTH #ARL#
......
......@@ -104,7 +104,8 @@ set @had_user_table= @@warning_count != 0;
CREATE TABLE IF NOT EXISTS roles_mapping ( Host char(60) binary DEFAULT '' NOT NULL, User char(80) binary DEFAULT '' NOT NULL, Role char(80) binary DEFAULT '' NOT NULL, Admin_option enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, UNIQUE (Host, User, Role)) engine=Aria transactional=1 CHARACTER SET utf8 COLLATE utf8_bin comment='Granted roles';
CREATE TABLE IF NOT EXISTS func ( name char(64) binary DEFAULT '' NOT NULL, ret tinyint(1) DEFAULT '0' NOT NULL, dl char(128) DEFAULT '' NOT NULL, type enum ('function','aggregate') COLLATE utf8_general_ci NOT NULL, PRIMARY KEY (name) ) engine=Aria transactional=1 CHARACTER SET utf8 COLLATE utf8_bin comment='User defined functions';
CREATE TABLE IF NOT EXISTS func ( name char(64) binary NOT NULL CHECK (name <> ''), ret tinyint(1) DEFAULT '0' NOT NULL CHECK (ret <> 3 AND ret BETWEEN 0 AND 4), dl char(128) NOT NULL CHECK (dl <> ''), type enum ('function','aggregate') COLLATE utf8_general_ci NOT NULL, PRIMARY KEY (name) ) engine=Aria transactional=1 CHARACTER SET utf8 COLLATE utf8_bin comment='User defined functions';
CREATE TABLE IF NOT EXISTS plugin ( name varchar(64) DEFAULT '' NOT NULL, dl varchar(128) DEFAULT '' NOT NULL, PRIMARY KEY (name) ) engine=Aria transactional=1 CHARACTER SET utf8 COLLATE utf8_general_ci comment='MySQL plugins';
......
......@@ -108,10 +108,14 @@ ALTER TABLE columns_priv
COLLATE utf8_general_ci DEFAULT '' NOT NULL;
#
# Add the new 'type' column to the func table.
# Add CHECK for 'name','ret','dl' field.
#
DELETE FROM func WHERE name='' OR ret=3 OR NOT ret BETWEEN 0 AND 4 OR dl='';
ALTER TABLE func add type enum ('function','aggregate') COLLATE utf8_general_ci NOT NULL;
ALTER TABLE func
MODIFY name char(64) binary NOT NULL CHECK (name <> ''),
MODIFY ret tinyint(1) DEFAULT '0' NOT NULL CHECK (ret <> 3 AND ret BETWEEN 0 AND 4),
MODIFY dl char(128) NOT NULL CHECK (dl <> '');
#
# Change the user,db and host tables to current format
......
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