1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

MDEV-36179 Assertion `0' failed in virtual bool Type_handler_row::Item_save_in_value(THD*, Item*, st_value*) const

sp_head::execute_procedure() and sp_head::execute_function() did not
check that Item_param could be passed as an actual parameter to a ROW type
formal parameter of a stored routine. Example:

CREATE PROCEDURE p0(OUT a ROW(a INT,b INT)) ...;
PREPARE s0 'CALL p0(?)';
EXECUTE p0 USING @a;

In case of passing a user variable as an OUT parameter it led to
a crash after executing routine instructions, when copying formal
OUT parameters to the bound actual parameters.

Fix:
Check cases when Item_param is being bound to a ROW type formal parameter.
Raise an error if so. The new check is done for all parameter modes:
IN, OUT, INOUT, for a consistent error message.

The new check is done before executing the routine instructions.
This commit is contained in:
Alexander Barkov
2025-03-19 16:05:35 +04:00
parent 1756b0f37d
commit 2ae721f2ad
3 changed files with 139 additions and 0 deletions

View File

@@ -2313,3 +2313,44 @@ SELECT 1 LIKE 2 ESCAPE a;
END; END;
$$ $$
ERROR 21000: Operand should contain 1 column(s) ERROR 21000: Operand should contain 1 column(s)
# Start of 10.6 tests
#
# MDEV-36179 Assertion `0' failed in virtual bool Type_handler_row::Item_save_in_value(THD*, Item*, st_value*) const
#
CREATE PROCEDURE p0 (IN a ROW(a INT,b INT))
BEGIN
SET a=ROW(0,0);
END;
/
PREPARE s0 FROM 'CALL p0(?)';
EXECUTE s0 USING @a;
ERROR HY000: Illegal parameter data type row for operation 'EXECUTE ... USING ?'
DROP PROCEDURE p0;
CREATE PROCEDURE p0 (INOUT a ROW(a INT,b INT))
BEGIN
SET a=ROW(0,0);
END;
/
PREPARE s0 FROM 'CALL p0(?)';
EXECUTE s0 USING @a;
ERROR HY000: Illegal parameter data type row for operation 'EXECUTE ... USING ?'
DROP PROCEDURE p0;
CREATE PROCEDURE p0 (OUT a ROW(a INT,b INT))
BEGIN
SET a=ROW(0,0);
END;
/
PREPARE s0 FROM 'CALL p0(?)';
EXECUTE s0 USING @a;
ERROR HY000: Illegal parameter data type row for operation 'EXECUTE ... USING ?'
DROP PROCEDURE p0;
CREATE FUNCTION f0(a ROW(a INT,b INT)) RETURNS BOOLEAN
BEGIN
RETURN FALSE;
END;
/
PREPARE s0 FROM 'SELECT f0(?)';
EXECUTE s0 USING @a;
ERROR HY000: Illegal parameter data type row for operation 'EXECUTE ... USING ?'
DROP FUNCTION f0;
# End of 10.6 tests

View File

@@ -1544,3 +1544,64 @@ BEGIN NOT ATOMIC
END; END;
$$ $$
DELIMITER ;$$ DELIMITER ;$$
--echo # Start of 10.6 tests
--echo #
--echo # MDEV-36179 Assertion `0' failed in virtual bool Type_handler_row::Item_save_in_value(THD*, Item*, st_value*) const
--echo #
DELIMITER /;
CREATE PROCEDURE p0 (IN a ROW(a INT,b INT))
BEGIN
SET a=ROW(0,0);
END;
/
DELIMITER ;/
PREPARE s0 FROM 'CALL p0(?)';
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
EXECUTE s0 USING @a;
DROP PROCEDURE p0;
DELIMITER /;
CREATE PROCEDURE p0 (INOUT a ROW(a INT,b INT))
BEGIN
SET a=ROW(0,0);
END;
/
DELIMITER ;/
PREPARE s0 FROM 'CALL p0(?)';
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
EXECUTE s0 USING @a;
DROP PROCEDURE p0;
DELIMITER /;
CREATE PROCEDURE p0 (OUT a ROW(a INT,b INT))
BEGIN
SET a=ROW(0,0);
END;
/
DELIMITER ;/
PREPARE s0 FROM 'CALL p0(?)';
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
EXECUTE s0 USING @a;
DROP PROCEDURE p0;
DELIMITER /;
CREATE FUNCTION f0(a ROW(a INT,b INT)) RETURNS BOOLEAN
BEGIN
RETURN FALSE;
END;
/
DELIMITER ;/
PREPARE s0 FROM 'SELECT f0(?)';
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
EXECUTE s0 USING @a;
DROP FUNCTION f0;
--echo # End of 10.6 tests

View File

@@ -2114,6 +2114,27 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount,
/* Arguments must be fixed in Item_func_sp::fix_fields */ /* Arguments must be fixed in Item_func_sp::fix_fields */
DBUG_ASSERT(argp[arg_no]->fixed()); DBUG_ASSERT(argp[arg_no]->fixed());
sp_variable *spvar= m_pcont->find_variable(arg_no);
if (!spvar)
continue;
/*
When you get a merge conflict, please move this code
into bind_input_param(). This also applies to the similar
code in execute_procedure().
*/
if (!spvar->field_def.type_handler()->is_scalar_type() &&
dynamic_cast<Item_param*>(argp[arg_no]))
{
// Item_param cannot store values of non-scalar data types yet
my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
spvar->field_def.type_handler()->name().ptr(),
"EXECUTE ... USING ?");
err_status= true;
goto err_with_cleanup;
}
if ((err_status= (*func_ctx)->set_parameter(thd, arg_no, &(argp[arg_no])))) if ((err_status= (*func_ctx)->set_parameter(thd, arg_no, &(argp[arg_no]))))
goto err_with_cleanup; goto err_with_cleanup;
} }
@@ -2359,11 +2380,27 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
if (!arg_item) if (!arg_item)
break; break;
/*
When you get a merge conflict, please move this code
into bind_input_param(). This also applies to the similar
code in execute_function().
*/
sp_variable *spvar= m_pcont->find_variable(i); sp_variable *spvar= m_pcont->find_variable(i);
if (!spvar) if (!spvar)
continue; continue;
if (!spvar->field_def.type_handler()->is_scalar_type() &&
dynamic_cast<Item_param*>(arg_item))
{
// Item_param cannot store values of non-scalar data types yet
my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
spvar->field_def.type_handler()->name().ptr(),
"EXECUTE ... USING ?");
err_status= true;
break;
}
if (spvar->mode != sp_variable::MODE_IN) if (spvar->mode != sp_variable::MODE_IN)
{ {
Settable_routine_parameter *srp= Settable_routine_parameter *srp=