Bug#17261 Passing a variable from a stored procedure to UDF crashes mysqld
- Pass "buffers[i]" to val_str() in udf_handler::fix_fields insteead of NULL. - Add testcase for UDF that will load and run the udf_example functions if available sql/item_func.cc: Instead of passing a NULL pointer into val_str, use the "buffers" array to provide a temp string buffer. sql/udf_example.cc: Spelling error"on"->"one" mysql-test/include/have_udf.inc: New BitKeeper file ``mysql-test/include/have_udf.inc'' mysql-test/r/have_udf.require: New BitKeeper file ``mysql-test/r/have_udf.require'' mysql-test/r/udf.result: New BitKeeper file ``mysql-test/r/udf.result'' mysql-test/t/udf.test: New BitKeeper file ``mysql-test/t/udf.test''
This commit is contained in:
parent
86c920ba77
commit
79258e4480
12
mysql-test/include/have_udf.inc
Normal file
12
mysql-test/include/have_udf.inc
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#
|
||||||
|
# To check if the udf_example.so is available,
|
||||||
|
# try to load one function from it.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
--require r/have_udf.require
|
||||||
|
--disable_abort_on_error
|
||||||
|
CREATE FUNCTION metaphon RETURNS STRING SONAME 'udf_example.so';
|
||||||
|
--disable_query_log
|
||||||
|
DROP FUNCTION metaphon;
|
||||||
|
--enable_query_log
|
||||||
|
--enable_abort_on_error
|
1
mysql-test/r/have_udf.require
Normal file
1
mysql-test/r/have_udf.require
Normal file
@ -0,0 +1 @@
|
|||||||
|
CREATE FUNCTION metaphon RETURNS STRING SONAME 'udf_example.so';
|
86
mysql-test/r/udf.result
Normal file
86
mysql-test/r/udf.result
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
drop table if exists t1;
|
||||||
|
CREATE FUNCTION metaphon RETURNS STRING SONAME 'udf_example.so';
|
||||||
|
CREATE FUNCTION myfunc_double RETURNS REAL SONAME 'udf_example.so';
|
||||||
|
CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME 'udf_example.so';
|
||||||
|
ERROR HY000: Can't find function 'myfunc_int_init' in library
|
||||||
|
CREATE FUNCTION sequence RETURNS INTEGER SONAME "udf_example.so";
|
||||||
|
CREATE FUNCTION lookup RETURNS STRING SONAME 'udf_example.so';
|
||||||
|
CREATE FUNCTION reverse_lookup
|
||||||
|
RETURNS STRING SONAME 'udf_example.so';
|
||||||
|
CREATE AGGREGATE FUNCTION avgcost
|
||||||
|
RETURNS REAL SONAME 'udf_example.so';
|
||||||
|
select myfunc_double();
|
||||||
|
ERROR HY000: myfunc_double must have at least on argument
|
||||||
|
select myfunc_double(1);
|
||||||
|
myfunc_double(1)
|
||||||
|
49.00
|
||||||
|
select myfunc_double(78654);
|
||||||
|
myfunc_double(78654)
|
||||||
|
54.00
|
||||||
|
select myfunc_int();
|
||||||
|
ERROR 42000: FUNCTION test.myfunc_int does not exist
|
||||||
|
select lookup();
|
||||||
|
ERROR HY000: Wrong arguments to lookup; Use the source
|
||||||
|
select lookup("127.0.0.1");
|
||||||
|
lookup("127.0.0.1")
|
||||||
|
127.0.0.1
|
||||||
|
select lookup(127,0,0,1);
|
||||||
|
ERROR HY000: Wrong arguments to lookup; Use the source
|
||||||
|
select lookup("localhost");
|
||||||
|
lookup("localhost")
|
||||||
|
127.0.0.1
|
||||||
|
select reverse_lookup();
|
||||||
|
ERROR HY000: Wrong number of arguments to reverse_lookup; Use the source
|
||||||
|
select reverse_lookup("127.0.0.1");
|
||||||
|
reverse_lookup("127.0.0.1")
|
||||||
|
localhost
|
||||||
|
select reverse_lookup(127,0,0,1);
|
||||||
|
reverse_lookup(127,0,0,1)
|
||||||
|
localhost
|
||||||
|
select reverse_lookup("localhost");
|
||||||
|
reverse_lookup("localhost")
|
||||||
|
NULL
|
||||||
|
select avgcost();
|
||||||
|
ERROR HY000: wrong number of arguments: AVGCOST() requires two arguments
|
||||||
|
select avgcost(100,23.76);
|
||||||
|
ERROR HY000: wrong argument type: AVGCOST() requires an INT and a REAL
|
||||||
|
create table t1(sum int, price float(24));
|
||||||
|
insert into t1 values(100, 50.00), (100, 100.00);
|
||||||
|
select avgcost(sum, price) from t1;
|
||||||
|
avgcost(sum, price)
|
||||||
|
75.0000
|
||||||
|
delete from t1;
|
||||||
|
insert into t1 values(100, 54.33), (200, 199.99);
|
||||||
|
select avgcost(sum, price) from t1;
|
||||||
|
avgcost(sum, price)
|
||||||
|
151.4367
|
||||||
|
drop table t1;
|
||||||
|
select metaphon('hello');
|
||||||
|
metaphon('hello')
|
||||||
|
HL
|
||||||
|
CREATE PROCEDURE `XXX1`(in testval varchar(10))
|
||||||
|
begin
|
||||||
|
select metaphon(testval);
|
||||||
|
end//
|
||||||
|
call XXX1('hello');
|
||||||
|
metaphon(testval)
|
||||||
|
HL
|
||||||
|
drop procedure xxx1;
|
||||||
|
CREATE PROCEDURE `XXX2`()
|
||||||
|
begin
|
||||||
|
declare testval varchar(10);
|
||||||
|
set testval = 'hello';
|
||||||
|
select metaphon(testval);
|
||||||
|
end//
|
||||||
|
call XXX2();
|
||||||
|
metaphon(testval)
|
||||||
|
HL
|
||||||
|
drop procedure xxx2;
|
||||||
|
DROP FUNCTION metaphon;
|
||||||
|
DROP FUNCTION myfunc_double;
|
||||||
|
DROP FUNCTION myfunc_int;
|
||||||
|
ERROR 42000: FUNCTION test.myfunc_int does not exist
|
||||||
|
DROP FUNCTION sequence;
|
||||||
|
DROP FUNCTION lookup;
|
||||||
|
DROP FUNCTION reverse_lookup;
|
||||||
|
DROP FUNCTION avgcost;
|
94
mysql-test/t/udf.test
Normal file
94
mysql-test/t/udf.test
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
--source include/have_udf.inc
|
||||||
|
#
|
||||||
|
# To run this tests you need to compile "sql/udf_example.cc" into
|
||||||
|
# udf_example.so and setup LD_LIBRARY_PATH to point out where
|
||||||
|
# the library are.
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
drop table if exists t1;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
#
|
||||||
|
# Create the example functions from udf_example
|
||||||
|
#
|
||||||
|
|
||||||
|
CREATE FUNCTION metaphon RETURNS STRING SONAME 'udf_example.so';
|
||||||
|
CREATE FUNCTION myfunc_double RETURNS REAL SONAME 'udf_example.so';
|
||||||
|
|
||||||
|
# myfunc_int does not have a myfunc_int_init function and can
|
||||||
|
# not be loaded unless server is started with --allow-suspicious-udfs
|
||||||
|
--error 1127
|
||||||
|
CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME 'udf_example.so';
|
||||||
|
CREATE FUNCTION sequence RETURNS INTEGER SONAME "udf_example.so";
|
||||||
|
CREATE FUNCTION lookup RETURNS STRING SONAME 'udf_example.so';
|
||||||
|
CREATE FUNCTION reverse_lookup
|
||||||
|
RETURNS STRING SONAME 'udf_example.so';
|
||||||
|
CREATE AGGREGATE FUNCTION avgcost
|
||||||
|
RETURNS REAL SONAME 'udf_example.so';
|
||||||
|
|
||||||
|
select myfunc_double();
|
||||||
|
select myfunc_double(1);
|
||||||
|
select myfunc_double(78654);
|
||||||
|
select myfunc_int();
|
||||||
|
select lookup();
|
||||||
|
select lookup("127.0.0.1");
|
||||||
|
select lookup(127,0,0,1);
|
||||||
|
select lookup("localhost");
|
||||||
|
select reverse_lookup();
|
||||||
|
select reverse_lookup("127.0.0.1");
|
||||||
|
select reverse_lookup(127,0,0,1);
|
||||||
|
select reverse_lookup("localhost");
|
||||||
|
select avgcost();
|
||||||
|
select avgcost(100,23.76);
|
||||||
|
create table t1(sum int, price float(24));
|
||||||
|
insert into t1 values(100, 50.00), (100, 100.00);
|
||||||
|
select avgcost(sum, price) from t1;
|
||||||
|
delete from t1;
|
||||||
|
insert into t1 values(100, 54.33), (200, 199.99);
|
||||||
|
select avgcost(sum, price) from t1;
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
# BUG#17261 Passing a variable from a stored procedure to UDF crashes mysqld
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
|
||||||
|
select metaphon('hello');
|
||||||
|
|
||||||
|
delimiter //;
|
||||||
|
CREATE PROCEDURE `XXX1`(in testval varchar(10))
|
||||||
|
begin
|
||||||
|
select metaphon(testval);
|
||||||
|
end//
|
||||||
|
delimiter ;//
|
||||||
|
|
||||||
|
call XXX1('hello');
|
||||||
|
drop procedure xxx1;
|
||||||
|
|
||||||
|
delimiter //;
|
||||||
|
CREATE PROCEDURE `XXX2`()
|
||||||
|
begin
|
||||||
|
declare testval varchar(10);
|
||||||
|
set testval = 'hello';
|
||||||
|
select metaphon(testval);
|
||||||
|
end//
|
||||||
|
delimiter ;//
|
||||||
|
|
||||||
|
call XXX2();
|
||||||
|
drop procedure xxx2;
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Drop the example functions from udf_example
|
||||||
|
#
|
||||||
|
|
||||||
|
DROP FUNCTION metaphon;
|
||||||
|
DROP FUNCTION myfunc_double;
|
||||||
|
--error 1305
|
||||||
|
DROP FUNCTION myfunc_int;
|
||||||
|
DROP FUNCTION sequence;
|
||||||
|
DROP FUNCTION lookup;
|
||||||
|
DROP FUNCTION reverse_lookup;
|
||||||
|
DROP FUNCTION avgcost;
|
||||||
|
|
@ -2606,7 +2606,7 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func,
|
|||||||
switch(arguments[i]->type()) {
|
switch(arguments[i]->type()) {
|
||||||
case Item::STRING_ITEM: // Constant string !
|
case Item::STRING_ITEM: // Constant string !
|
||||||
{
|
{
|
||||||
String *res=arguments[i]->val_str((String *) 0);
|
String *res=arguments[i]->val_str(&buffers[i]);
|
||||||
if (arguments[i]->null_value)
|
if (arguments[i]->null_value)
|
||||||
continue;
|
continue;
|
||||||
f_args.args[i]= (char*) res->ptr();
|
f_args.args[i]= (char*) res->ptr();
|
||||||
|
@ -518,7 +518,7 @@ my_bool myfunc_double_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
|
|||||||
{
|
{
|
||||||
if (!args->arg_count)
|
if (!args->arg_count)
|
||||||
{
|
{
|
||||||
strcpy(message,"myfunc_double must have at least on argument");
|
strcpy(message,"myfunc_double must have at least one argument");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user