1
0
mirror of https://github.com/MariaDB/server.git synced 2026-10-23 18:49:29 +03:00

MDEV-38451 SHOW FUNCTION CODE package_func crashes on the second execution

Routine name resolution performed on a temporary memory root
during execution. So on the second execution LEX::spname members
pointed to a cleared memory.

Fixing to peform the resolution to parse time, like the CALL statement does.
During the execution time LEX::spname members now stay untouched.
This commit is contained in:
Alexander Barkov
2025-12-29 18:03:23 +04:00
parent 29a986a024
commit 4de773e90c
8 changed files with 149 additions and 36 deletions

View File

@@ -243,3 +243,33 @@ Pos Instruction
7 jump 11
DROP PACKAGE pkg1;
DROP TABLE t1;
# Start of 10.11 tests
#
# MDEV-38451 `SHOW FUNCTION CODE package_func` crashes on the second execution
#
CREATE PACKAGE pkg1 AS
PROCEDURE p1();
END;
$$
CREATE PACKAGE BODY pkg1 AS
FUNCTION f1() RETURN INT AS
BEGIN
RETURN 10;
END;
PROCEDURE p1() AS
BEGIN
SHOW FUNCTION CODE f1;
END;
END;
$$
CALL pkg1.p1;
Pos Instruction
0 freturn int 10
CALL pkg1.p1;
Pos Instruction
0 freturn int 10
CALL pkg1.p1;
Pos Instruction
0 freturn int 10
DROP PACKAGE pkg1;
# End of 10.11 tests

View File

@@ -180,3 +180,33 @@ SHOW PROCEDURE CODE pkg1.p1;
SHOW PACKAGE BODY CODE pkg1;
DROP PACKAGE pkg1;
DROP TABLE t1;
--echo # Start of 10.11 tests
--echo #
--echo # MDEV-38451 `SHOW FUNCTION CODE package_func` crashes on the second execution
--echo #
DELIMITER $$;
CREATE PACKAGE pkg1 AS
PROCEDURE p1();
END;
$$
CREATE PACKAGE BODY pkg1 AS
FUNCTION f1() RETURN INT AS
BEGIN
RETURN 10;
END;
PROCEDURE p1() AS
BEGIN
SHOW FUNCTION CODE f1;
END;
END;
$$
DELIMITER ;$$
CALL pkg1.p1;
CALL pkg1.p1;
CALL pkg1.p1;
DROP PACKAGE pkg1;
--echo # End of 10.11 tests

View File

@@ -8120,6 +8120,8 @@ class Database_qualified_name
public:
LEX_CSTRING m_db;
LEX_CSTRING m_name;
Database_qualified_name()
{ }
Database_qualified_name(const LEX_CSTRING *db, const LEX_CSTRING *name)
:m_db(*db), m_name(*name)
{ }

View File

@@ -180,4 +180,38 @@ public:
}
};
#ifndef DBUG_OFF
/**
Sql_cmd_call represents the SHOW CODE statement:
- SHOW PROCEDURE CODE
- SHOW FUNCTION CODE
- SHOW PACKAGE BODY CODE
*/
class Sql_cmd_show_routine_code : public Sql_cmd
{
public:
class sp_name *m_name;
const class Sp_handler *m_handler;
enum_sql_command m_sql_command;
Sql_cmd_show_routine_code(class sp_name *name,
const class Sp_handler *handler,
enum_sql_command sql_command)
:m_name(name),
m_handler(handler),
m_sql_command(sql_command)
{}
virtual ~Sql_cmd_show_routine_code() = default;
bool execute(THD *thd) override;
enum_sql_command sql_command_code() const override
{
return m_sql_command;
}
};
#endif // DBUG_OFF
#endif // SQL_CMD_INCLUDED

View File

@@ -9390,6 +9390,27 @@ bool LEX::add_create_view(THD *thd, DDL_options_st ddl,
}
bool LEX::show_routine_code_start(THD *thd, enum_sql_command cmd, sp_name *name)
{
#ifdef DBUG_OFF
my_error(ER_FEATURE_DISABLED, MYF(0),
"SHOW PROCEDURE|FUNCTION CODE", "--with-debug");
return true;
#else
sql_command= cmd;
Database_qualified_name pkgname;
const Sp_handler *sph= Sp_handler::handler(cmd);
if (sph->sp_resolve_package_routine(thd, thd->lex->sphead,
name, &sph, &pkgname))
return true;
if (!(m_sql_cmd= new (thd->mem_root) Sql_cmd_show_routine_code(name, sph,
cmd)))
return true;
return false;
#endif
}
bool LEX::call_statement_start(THD *thd, sp_name *name)
{
Database_qualified_name pkgname(&null_clex_str, &null_clex_str);

View File

@@ -3971,6 +3971,7 @@ public:
const sp_name *name,
const sp_name *name2,
const char *cpp_body_end);
bool show_routine_code_start(THD *thd, enum_sql_command cmd, sp_name *name);
bool call_statement_start(THD *thd, sp_name *name);
bool call_statement_start(THD *thd, const Lex_ident_sys_st *name);
bool call_statement_start(THD *thd, const Lex_ident_sys_st *name1,

View File

@@ -3288,6 +3288,24 @@ static bool prepare_db_action(THD *thd, privilege_t want_access,
}
#ifndef DBUG_OFF
bool Sql_cmd_show_routine_code::execute(THD *thd)
{
sp_head *sp;
if (m_handler->sp_cache_routine(thd, m_name, &sp))
return true;
if (!sp || sp->show_routine_code(thd))
{
/* We don't distinguish between errors for now */
my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
m_handler->type_str(), m_name->m_name.str);
return true;
}
return false;
}
#endif // DBUG_OFF
bool Sql_cmd_call::execute(THD *thd)
{
TABLE_LIST *all_tables= thd->lex->query_tables;
@@ -5967,34 +5985,6 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
goto error;
break;
}
case SQLCOM_SHOW_PROC_CODE:
case SQLCOM_SHOW_FUNC_CODE:
case SQLCOM_SHOW_PACKAGE_BODY_CODE:
{
#ifndef DBUG_OFF
Database_qualified_name pkgname(&null_clex_str, &null_clex_str);
sp_head *sp;
const Sp_handler *sph= Sp_handler::handler(lex->sql_command);
WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_SHOW);
if (sph->sp_resolve_package_routine(thd, thd->lex->sphead,
lex->spname, &sph, &pkgname))
return true;
if (sph->sp_cache_routine(thd, lex->spname, &sp))
goto error;
if (!sp || sp->show_routine_code(thd))
{
/* We don't distinguish between errors for now */
my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
sph->type_str(), lex->spname->m_name.str);
goto error;
}
break;
#else
my_error(ER_FEATURE_DISABLED, MYF(0),
"SHOW PROCEDURE|FUNCTION CODE", "--with-debug");
goto error;
#endif // ifndef DBUG_OFF
}
case SQLCOM_SHOW_CREATE_TRIGGER:
{
if (check_ident_length(&lex->spname->m_name))
@@ -6199,6 +6189,9 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
case SQLCOM_SIGNAL:
case SQLCOM_RESIGNAL:
case SQLCOM_GET_DIAGNOSTICS:
case SQLCOM_SHOW_PROC_CODE:
case SQLCOM_SHOW_FUNC_CODE:
case SQLCOM_SHOW_PACKAGE_BODY_CODE:
case SQLCOM_CALL:
case SQLCOM_REVOKE:
case SQLCOM_GRANT:

View File

@@ -14024,23 +14024,25 @@ show_param:
}
| PROCEDURE_SYM CODE_SYM sp_name
{
Lex->sql_command= SQLCOM_SHOW_PROC_CODE;
Lex->spname= $3;
if (Lex->show_routine_code_start(thd, SQLCOM_SHOW_PROC_CODE, $3))
MYSQL_YYABORT;
}
| FUNCTION_SYM CODE_SYM sp_name
{
Lex->sql_command= SQLCOM_SHOW_FUNC_CODE;
Lex->spname= $3;
if (Lex->show_routine_code_start(thd, SQLCOM_SHOW_FUNC_CODE, $3))
MYSQL_YYABORT;
}
| PACKAGE_MARIADB_SYM BODY_MARIADB_SYM CODE_SYM sp_name
{
Lex->sql_command= SQLCOM_SHOW_PACKAGE_BODY_CODE;
Lex->spname= $4;
if (Lex->show_routine_code_start(thd, SQLCOM_SHOW_PACKAGE_BODY_CODE,
$4))
MYSQL_YYABORT;
}
| PACKAGE_ORACLE_SYM BODY_ORACLE_SYM CODE_SYM sp_name
{
Lex->sql_command= SQLCOM_SHOW_PACKAGE_BODY_CODE;
Lex->spname= $4;
if (Lex->show_routine_code_start(thd, SQLCOM_SHOW_PACKAGE_BODY_CODE,
$4))
MYSQL_YYABORT;
}
| CREATE EVENT_SYM sp_name
{