Commit 4ced38b8 authored by unknown's avatar unknown

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.


mysql-test/r/udf.result:
  Bug #25382: Passing NULL to an UDF called from stored procedures 
   crashes server
   - test case
mysql-test/t/udf.test:
  Bug #25382: Passing NULL to an UDF called from stored procedures 
   crashes server
   - test case
sql/item_func.cc:
  Bug #25382: Passing NULL to an UDF called from stored procedures 
   crashes server
   - reliably check null_value
parent 6746efb1
...@@ -240,3 +240,37 @@ drop table bug18761; ...@@ -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; ...@@ -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, ...@@ -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;
......
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