Bug #25382: Passing NULL to an UDF called from stored procedures
crashes server Check for null value is reliable only after calling some of the val_xxx() methods. If the val_xxx() method is not called the null_value flag will be set only for certain types of NULL values (like SQL constant NULLs for example). This caused a crash while trying to dereference a NULL pointer that is returned by val_str() for NULL values. Fixed by swapping the order of val_xxx() and null_value check.
This commit is contained in:
parent
12c6e9d2b0
commit
20d94f1105
@ -240,3 +240,37 @@ drop table bug18761;
|
|||||||
select is_const((1,2,3));
|
select is_const((1,2,3));
|
||||||
ERROR 21000: Operand should contain 1 column(s)
|
ERROR 21000: Operand should contain 1 column(s)
|
||||||
drop function if exists is_const;
|
drop function if exists is_const;
|
||||||
|
CREATE FUNCTION metaphon RETURNS STRING SONAME "UDF_EXAMPLE_LIB";
|
||||||
|
CREATE FUNCTION myfunc_double RETURNS REAL SONAME "UDF_EXAMPLE_LIB";
|
||||||
|
CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME "UDF_EXAMPLE_LIB";
|
||||||
|
create function f1(p1 varchar(255))
|
||||||
|
returns varchar(255)
|
||||||
|
begin
|
||||||
|
return metaphon(p1);
|
||||||
|
end//
|
||||||
|
create function f2(p1 varchar(255))
|
||||||
|
returns double
|
||||||
|
begin
|
||||||
|
return myfunc_double(p1);
|
||||||
|
end//
|
||||||
|
create function f3(p1 varchar(255))
|
||||||
|
returns double
|
||||||
|
begin
|
||||||
|
return myfunc_int(p1);
|
||||||
|
end//
|
||||||
|
select f3(NULL);
|
||||||
|
f3(NULL)
|
||||||
|
0
|
||||||
|
select f2(NULL);
|
||||||
|
f2(NULL)
|
||||||
|
NULL
|
||||||
|
select f1(NULL);
|
||||||
|
f1(NULL)
|
||||||
|
NULL
|
||||||
|
drop function f1;
|
||||||
|
drop function f2;
|
||||||
|
drop function f3;
|
||||||
|
drop function metaphon;
|
||||||
|
drop function myfunc_double;
|
||||||
|
drop function myfunc_int;
|
||||||
|
End of 5.0 tests.
|
||||||
|
@ -242,3 +242,50 @@ drop table bug18761;
|
|||||||
select is_const((1,2,3));
|
select is_const((1,2,3));
|
||||||
|
|
||||||
drop function if exists is_const;
|
drop function if exists is_const;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug #25382: Passing NULL to an UDF called from stored procedures
|
||||||
|
# crashes server
|
||||||
|
#
|
||||||
|
--replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB
|
||||||
|
eval CREATE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_LIB";
|
||||||
|
|
||||||
|
--replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB
|
||||||
|
eval CREATE FUNCTION myfunc_double RETURNS REAL SONAME "$UDF_EXAMPLE_LIB";
|
||||||
|
|
||||||
|
--replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB
|
||||||
|
eval CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME "$UDF_EXAMPLE_LIB";
|
||||||
|
|
||||||
|
delimiter //;
|
||||||
|
create function f1(p1 varchar(255))
|
||||||
|
returns varchar(255)
|
||||||
|
begin
|
||||||
|
return metaphon(p1);
|
||||||
|
end//
|
||||||
|
|
||||||
|
create function f2(p1 varchar(255))
|
||||||
|
returns double
|
||||||
|
begin
|
||||||
|
return myfunc_double(p1);
|
||||||
|
end//
|
||||||
|
|
||||||
|
create function f3(p1 varchar(255))
|
||||||
|
returns double
|
||||||
|
begin
|
||||||
|
return myfunc_int(p1);
|
||||||
|
end//
|
||||||
|
|
||||||
|
delimiter ;//
|
||||||
|
|
||||||
|
select f3(NULL);
|
||||||
|
select f2(NULL);
|
||||||
|
select f1(NULL);
|
||||||
|
|
||||||
|
drop function f1;
|
||||||
|
drop function f2;
|
||||||
|
drop function f3;
|
||||||
|
drop function metaphon;
|
||||||
|
drop function myfunc_double;
|
||||||
|
drop function myfunc_int;
|
||||||
|
|
||||||
|
--echo End of 5.0 tests.
|
||||||
|
@ -2729,25 +2729,28 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func,
|
|||||||
|
|
||||||
if (arguments[i]->const_item())
|
if (arguments[i]->const_item())
|
||||||
{
|
{
|
||||||
if (arguments[i]->null_value)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
switch (arguments[i]->result_type())
|
switch (arguments[i]->result_type())
|
||||||
{
|
{
|
||||||
case STRING_RESULT:
|
case STRING_RESULT:
|
||||||
case DECIMAL_RESULT:
|
case DECIMAL_RESULT:
|
||||||
{
|
{
|
||||||
String *res= arguments[i]->val_str(&buffers[i]);
|
String *res= arguments[i]->val_str(&buffers[i]);
|
||||||
|
if (arguments[i]->null_value)
|
||||||
|
continue;
|
||||||
f_args.args[i]= (char*) res->ptr();
|
f_args.args[i]= (char*) res->ptr();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case INT_RESULT:
|
case INT_RESULT:
|
||||||
*((longlong*) to)= arguments[i]->val_int();
|
*((longlong*) to)= arguments[i]->val_int();
|
||||||
|
if (arguments[i]->null_value)
|
||||||
|
continue;
|
||||||
f_args.args[i]= to;
|
f_args.args[i]= to;
|
||||||
to+= ALIGN_SIZE(sizeof(longlong));
|
to+= ALIGN_SIZE(sizeof(longlong));
|
||||||
break;
|
break;
|
||||||
case REAL_RESULT:
|
case REAL_RESULT:
|
||||||
*((double*) to)= arguments[i]->val_real();
|
*((double*) to)= arguments[i]->val_real();
|
||||||
|
if (arguments[i]->null_value)
|
||||||
|
continue;
|
||||||
f_args.args[i]= to;
|
f_args.args[i]= to;
|
||||||
to+= ALIGN_SIZE(sizeof(double));
|
to+= ALIGN_SIZE(sizeof(double));
|
||||||
break;
|
break;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user