diff --git a/mysql-test/main/servers.result b/mysql-test/main/servers.result index ea7567ecfef..bf96107c945 100644 --- a/mysql-test/main/servers.result +++ b/mysql-test/main/servers.result @@ -200,4 +200,10 @@ show create server s1; Server Create Server s1 CREATE SERVER `s1` FOREIGN DATA WRAPPER `my'sql` OPTIONS (`ho``st` 'va''lue'); drop server s1; +# +# MDEV-41064 MariaDB Server stack overflow when FLUSH PRIVILEGES parses a large JSON value from mysql.servers.Options inside a stored procedure +# +INSERT INTO mysql.servers (Server_name, Options) VALUES ('t1', CONCAT('{"x": "', REPEAT('a', 12000000), '"}')); +FLUSH PRIVILEGES; +DELETE FROM mysql.servers WHERE Server_name = 't1'; # End of 11.8 tests diff --git a/mysql-test/main/servers.test b/mysql-test/main/servers.test index 2e58fc2a4e9..caf619d1b74 100644 --- a/mysql-test/main/servers.test +++ b/mysql-test/main/servers.test @@ -200,4 +200,12 @@ create server s1 foreign data wrapper 'my''sql' options (`ho``st` 'va''lue'); show create server s1; drop server s1; +--echo # +--echo # MDEV-41064 MariaDB Server stack overflow when FLUSH PRIVILEGES parses a large JSON value from mysql.servers.Options inside a stored procedure +--echo # + +INSERT INTO mysql.servers (Server_name, Options) VALUES ('t1', CONCAT('{"x": "', REPEAT('a', 12000000), '"}')); +FLUSH PRIVILEGES; +DELETE FROM mysql.servers WHERE Server_name = 't1'; + --echo # End of 11.8 tests diff --git a/sql/sql_servers.cc b/sql/sql_servers.cc index 62fb12ef004..32ffe6c430e 100644 --- a/sql/sql_servers.cc +++ b/sql/sql_servers.cc @@ -356,14 +356,20 @@ static bool parse_server_options_json(FOREIGN_SERVER *server, char *ptr) if (option->value.length) { LEX_CSTRING *optval= &option->value; - char *unescaped= (char *) alloca(optval->length); + char *unescaped= (char *) my_safe_alloca(optval->length); + if (!unescaped) + DBUG_RETURN(TRUE); int len= json_unescape_json(optval->str, optval->str + optval->length, unescaped, unescaped + optval->length); if (len < 0) + { + my_safe_afree(unescaped, optval->length); DBUG_RETURN(TRUE); + } DBUG_ASSERT(len <= (int) optval->length); if (len < (int) optval->length) strncpy((char *) optval->str, unescaped, len); + my_safe_afree(unescaped, optval->length); optval->length= len; } }