3300 Tor Didriksen 2011-03-18 [merge]
local merge
modified:
mysql-test/include/have_plugin_auth.inc
mysql-test/suite/funcs_1/r/is_columns_is_embedded.result
mysql-test/suite/funcs_1/r/is_columns_myisam_embedded.result
mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result
mysql-test/suite/funcs_1/r/is_statistics_mysql_embedded.result
mysql-test/suite/funcs_1/r/is_table_constraints_mysql_embedded.result
mysql-test/suite/funcs_1/r/is_tables_mysql_embedded.result
mysql-test/t/mysql_client_test-master.opt
mysql-test/t/mysql_client_test.test
sql/ha_partition.cc
=== modified file 'include/decimal.h'
--- a/include/decimal.h 2007-05-24 10:24:36 +0000
+++ b/include/decimal.h 2011-03-03 14:25:41 +0000
@@ -29,14 +29,14 @@ typedef struct st_decimal_t {
int internal_str2dec(const char *from, decimal_t *to, char **end,
my_bool fixed);
-int decimal2string(decimal_t *from, char *to, int *to_len,
+int decimal2string(const decimal_t *from, char *to, int *to_len,
int fixed_precision, int fixed_decimals,
char filler);
int decimal2ulonglong(decimal_t *from, ulonglong *to);
int ulonglong2decimal(ulonglong from, decimal_t *to);
int decimal2longlong(decimal_t *from, longlong *to);
int longlong2decimal(longlong from, decimal_t *to);
-int decimal2double(decimal_t *from, double *to);
+int decimal2double(const decimal_t *from, double *to);
int double2decimal(double from, decimal_t *to);
int decimal_actual_fraction(decimal_t *from);
int decimal2bin(decimal_t *from, uchar *to, int precision, int scale);
@@ -47,17 +47,17 @@ int decimal_bin_size(int precision, int
int decimal_result_size(decimal_t *from1, decimal_t *from2, char op,
int param);
-int decimal_intg(decimal_t *from);
-int decimal_add(decimal_t *from1, decimal_t *from2, decimal_t *to);
-int decimal_sub(decimal_t *from1, decimal_t *from2, decimal_t *to);
-int decimal_cmp(decimal_t *from1, decimal_t *from2);
-int decimal_mul(decimal_t *from1, decimal_t *from2, decimal_t *to);
-int decimal_div(decimal_t *from1, decimal_t *from2, decimal_t *to,
+int decimal_intg(const decimal_t *from);
+int decimal_add(const decimal_t *from1, const decimal_t *from2, decimal_t *to);
+int decimal_sub(const decimal_t *from1, const decimal_t *from2, decimal_t *to);
+int decimal_cmp(const decimal_t *from1, const decimal_t *from2);
+int decimal_mul(const decimal_t *from1, const decimal_t *from2, decimal_t *to);
+int decimal_div(const decimal_t *from1, const decimal_t *from2, decimal_t *to,
int scale_incr);
-int decimal_mod(decimal_t *from1, decimal_t *from2, decimal_t *to);
-int decimal_round(decimal_t *from, decimal_t *to, int new_scale,
+int decimal_mod(const decimal_t *from1, const decimal_t *from2, decimal_t *to);
+int decimal_round(const decimal_t *from, decimal_t *to, int new_scale,
decimal_round_mode mode);
-int decimal_is_zero(decimal_t *from);
+int decimal_is_zero(const decimal_t *from);
void max_decimal(int precision, int frac, decimal_t *to);
#define string2decimal(A,B,C) internal_str2dec((A), (B), (C), 0)
=== modified file 'mysql-test/r/func_math.result'
--- a/mysql-test/r/func_math.result 2011-01-14 15:36:19 +0000
+++ b/mysql-test/r/func_math.result 2011-03-18 12:25:56 +0000
@@ -656,3 +656,11 @@ Warning 1366 Incorrect decimal value: ''
SELECT 1 div null;
1 div null
NULL
+#
+# Bug #11792200 - DIVIDING LARGE NUMBERS CAUSES STACK CORRUPTIONS
+#
+select (1.175494351E-37 div 1.7976931348623157E+308);
+(1.175494351E-37 div 1.7976931348623157E+308)
+0
+Warnings:
+Warning 1292 Truncated incorrect DECIMAL value: ''
=== modified file 'mysql-test/t/func_math.test'
--- a/mysql-test/t/func_math.test 2011-01-14 15:36:19 +0000
+++ b/mysql-test/t/func_math.test 2011-03-18 12:25:56 +0000
@@ -500,3 +500,8 @@ SELECT ((@a:=@b:=1.0) div (@b:=@a:=get_f
--echo # Bug #59498 div function broken in mysql-trunk
--echo #
SELECT 1 div null;
+
+--echo #
+--echo # Bug #11792200 - DIVIDING LARGE NUMBERS CAUSES STACK CORRUPTIONS
+--echo #
+select (1.175494351E-37 div 1.7976931348623157E+308);
=== modified file 'sql/my_decimal.h'
--- a/sql/my_decimal.h 2011-03-09 20:54:55 +0000
+++ b/sql/my_decimal.h 2011-03-18 12:25:56 +0000
@@ -178,7 +178,7 @@ void max_my_decimal(my_decimal *to, int
{
DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION)&&
(frac <= DECIMAL_MAX_SCALE));
- max_decimal(precision, frac, (decimal_t*) to);
+ max_decimal(precision, frac, to);
}
inline void max_internal_decimal(my_decimal *to)
@@ -277,14 +277,19 @@ inline
int binary2my_decimal(uint mask, const uchar *bin, my_decimal *d, int prec,
int scale)
{
- return check_result(mask, bin2decimal(bin, (decimal_t*) d, prec, scale));
+ return check_result(mask, bin2decimal(bin, d, prec, scale));
}
inline
int my_decimal_set_zero(my_decimal *d)
{
- decimal_make_zero(((decimal_t*) d));
+ /*
+ We need the up-cast here, since my_decimal has sign() member functions,
+ which conflicts with decimal_t::size
+ (and decimal_make_zero is a macro, rather than a funcion).
+ */
+ decimal_make_zero(static_cast<decimal_t*>(d));
return 0;
}
@@ -292,7 +297,7 @@ int my_decimal_set_zero(my_decimal *d)
inline
bool my_decimal_is_zero(const my_decimal *decimal_value)
{
- return decimal_is_zero((decimal_t*) decimal_value);
+ return decimal_is_zero(decimal_value);
}
@@ -300,7 +305,7 @@ inline
int my_decimal_round(uint mask, const my_decimal *from, int scale,
bool truncate, my_decimal *to)
{
- return check_result(mask, decimal_round((decimal_t*) from, to, scale,
+ return check_result(mask, decimal_round(from, to, scale,
(truncate ? TRUNCATE : HALF_UP)));
}
@@ -308,14 +313,14 @@ int my_decimal_round(uint mask, const my
inline
int my_decimal_floor(uint mask, const my_decimal *from, my_decimal *to)
{
- return check_result(mask, decimal_round((decimal_t*) from, to, 0, FLOOR));
+ return check_result(mask, decimal_round(from, to, 0, FLOOR));
}
inline
int my_decimal_ceiling(uint mask, const my_decimal *from, my_decimal *to)
{
- return check_result(mask, decimal_round((decimal_t*) from, to, 0, CEILING));
+ return check_result(mask, decimal_round(from, to, 0, CEILING));
}
@@ -337,7 +342,7 @@ int my_decimal2int(uint mask, const my_d
{
my_decimal rounded;
/* decimal_round can return only E_DEC_TRUNCATED */
- decimal_round((decimal_t*)d, &rounded, 0, HALF_UP);
+ decimal_round(d, &rounded, 0, HALF_UP);
return check_result(mask, (unsigned_flag ?
decimal2ulonglong(&rounded, (ulonglong *)l) :
decimal2longlong(&rounded, l)));
@@ -348,15 +353,14 @@ inline
int my_decimal2double(uint, const my_decimal *d, double *result)
{
/* No need to call check_result as this will always succeed */
- return decimal2double((decimal_t*) d, result);
+ return decimal2double(d, result);
}
inline
int str2my_decimal(uint mask, const char *str, my_decimal *d, char **end)
{
- return check_result_and_overflow(mask, string2decimal(str,(decimal_t*)d,end),
- d);
+ return check_result_and_overflow(mask, string2decimal(str, d, end), d);
}
@@ -379,7 +383,7 @@ my_decimal *date2my_decimal(MYSQL_TIME *
inline
int double2my_decimal(uint mask, double val, my_decimal *d)
{
- return check_result_and_overflow(mask, double2decimal(val, (decimal_t*)d), d);
+ return check_result_and_overflow(mask, double2decimal(val, d), d);
}
@@ -409,7 +413,7 @@ int my_decimal_add(uint mask, my_decimal
const my_decimal *b)
{
return check_result_and_overflow(mask,
- decimal_add((decimal_t*)a,(decimal_t*)b,res),
+ decimal_add(a, b, res),
res);
}
@@ -419,7 +423,7 @@ int my_decimal_sub(uint mask, my_decimal
const my_decimal *b)
{
return check_result_and_overflow(mask,
- decimal_sub((decimal_t*)a,(decimal_t*)b,res),
+ decimal_sub(a, b, res),
res);
}
@@ -429,7 +433,7 @@ int my_decimal_mul(uint mask, my_decimal
const my_decimal *b)
{
return check_result_and_overflow(mask,
- decimal_mul((decimal_t*)a,(decimal_t*)b,res),
+ decimal_mul(a, b, res),
res);
}
@@ -439,8 +443,7 @@ int my_decimal_div(uint mask, my_decimal
const my_decimal *b, int div_scale_inc)
{
return check_result_and_overflow(mask,
- decimal_div((decimal_t*)a,(decimal_t*)b,res,
- div_scale_inc),
+ decimal_div(a, b, res, div_scale_inc),
res);
}
@@ -450,7 +453,7 @@ int my_decimal_mod(uint mask, my_decimal
const my_decimal *b)
{
return check_result_and_overflow(mask,
- decimal_mod((decimal_t*)a,(decimal_t*)b,res),
+ decimal_mod(a, b, res),
res);
}
@@ -462,14 +465,14 @@ int my_decimal_mod(uint mask, my_decimal
inline
int my_decimal_cmp(const my_decimal *a, const my_decimal *b)
{
- return decimal_cmp((decimal_t*) a, (decimal_t*) b);
+ return decimal_cmp(a, b);
}
inline
int my_decimal_intg(const my_decimal *a)
{
- return decimal_intg((decimal_t*) a);
+ return decimal_intg(a);
}
=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc 2011-03-15 18:08:59 +0000
+++ b/sql/mysqld.cc 2011-03-18 12:25:56 +0000
@@ -2329,7 +2329,7 @@ LONG WINAPI my_unhandler_exception_filte
}
-static void init_signals(void)
+void my_init_signals(void)
{
if(opt_console)
SetConsoleCtrlHandler(console_event_handler,TRUE);
@@ -2550,11 +2550,11 @@ bugs.\n");
#ifndef EMBEDDED_LIBRARY
-static void init_signals(void)
+void my_init_signals(void)
{
sigset_t set;
struct sigaction sa;
- DBUG_ENTER("init_signals");
+ DBUG_ENTER("my_init_signals");
my_sigset(THR_SERVER_ALARM,print_signal_warning); // Should never be called!
@@ -4650,7 +4650,7 @@ int mysqld_main(int argc, char **argv)
if (init_common_variables())
unireg_abort(1); // Will do exit
- init_signals();
+ my_init_signals();
#if defined(__ia64__) || defined(__ia64)
/*
Peculiar things with ia64 platforms - it seems we only have half the
=== modified file 'sql/mysqld.h'
--- a/sql/mysqld.h 2011-03-15 13:03:22 +0000
+++ b/sql/mysqld.h 2011-03-18 12:25:56 +0000
@@ -76,6 +76,7 @@ bool is_secure_file_path(char *path);
// These are needed for unit testing.
void set_remaining_args(int argc, char **argv);
int init_common_variables();
+void my_init_signals();
extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *system_charset_info;
extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *files_charset_info ;
=== modified file 'strings/decimal.c'
--- a/strings/decimal.c 2011-01-19 13:31:17 +0000
+++ b/strings/decimal.c 2011-03-03 14:25:41 +0000
@@ -248,7 +248,7 @@ void max_decimal(int precision, int frac
}
-static dec1 *remove_leading_zeroes(decimal_t *from, int *intg_result)
+static dec1 *remove_leading_zeroes(const decimal_t *from, int *intg_result)
{
int intg= from->intg, i;
dec1 *buf0= from->buf;
@@ -326,7 +326,7 @@ int decimal_actual_fraction(decimal_t *f
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
*/
-int decimal2string(decimal_t *from, char *to, int *to_len,
+int decimal2string(const decimal_t *from, char *to, int *to_len,
int fixed_precision, int fixed_decimals,
char filler)
{
@@ -942,7 +942,7 @@ fatal_error:
E_DEC_OK/E_DEC_OVERFLOW/E_DEC_TRUNCATED
*/
-int decimal2double(decimal_t *from, double *to)
+int decimal2double(const decimal_t *from, double *to)
{
char strbuf[FLOATING_POINT_BUFFER], *end;
int len= sizeof(strbuf);
@@ -1461,7 +1461,7 @@ int decimal_bin_size(int precision, int
*/
int
-decimal_round(decimal_t *from, decimal_t *to, int scale,
+decimal_round(const decimal_t *from, decimal_t *to, int scale,
decimal_round_mode mode)
{
int frac0=scale>0 ? ROUND_UP(scale) : scale/DIG_PER_DEC1,
@@ -1695,7 +1695,7 @@ int decimal_result_size(decimal_t *from1
return -1; /* shut up the warning */
}
-static int do_add(decimal_t *from1, decimal_t *from2, decimal_t *to)
+static int do_add(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
{
int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
@@ -1777,7 +1777,7 @@ static int do_add(decimal_t *from1, deci
/* to=from1-from2.
if to==0, return -1/0/+1 - the result of the comparison */
-static int do_sub(decimal_t *from1, decimal_t *from2, decimal_t *to)
+static int do_sub(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
{
int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac);
@@ -1846,7 +1846,7 @@ static int do_sub(decimal_t *from1, deci
/* ensure that always from1 > from2 (and intg1 >= intg2) */
if (carry)
{
- swap_variables(decimal_t *,from1,from1);
+ swap_variables(const decimal_t *, from1, from2);
swap_variables(dec1 *,start1, start2);
swap_variables(int,intg1,intg2);
swap_variables(int,frac1,frac2);
@@ -1912,35 +1912,35 @@ static int do_sub(decimal_t *from1, deci
return error;
}
-int decimal_intg(decimal_t *from)
+int decimal_intg(const decimal_t *from)
{
int res;
remove_leading_zeroes(from, &res);
return res;
}
-int decimal_add(decimal_t *from1, decimal_t *from2, decimal_t *to)
+int decimal_add(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
{
if (likely(from1->sign == from2->sign))
return do_add(from1, from2, to);
return do_sub(from1, from2, to);
}
-int decimal_sub(decimal_t *from1, decimal_t *from2, decimal_t *to)
+int decimal_sub(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
{
if (likely(from1->sign == from2->sign))
return do_sub(from1, from2, to);
return do_add(from1, from2, to);
}
-int decimal_cmp(decimal_t *from1, decimal_t *from2)
+int decimal_cmp(const decimal_t *from1, const decimal_t *from2)
{
if (likely(from1->sign == from2->sign))
return do_sub(from1, from2, 0);
return from1->sign > from2->sign ? -1 : 1;
}
-int decimal_is_zero(decimal_t *from)
+int decimal_is_zero(const decimal_t *from)
{
dec1 *buf1=from->buf,
*end=buf1+ROUND_UP(from->intg)+ROUND_UP(from->frac);
@@ -1971,7 +1971,7 @@ int decimal_is_zero(decimal_t *from)
XXX if this library is to be used with huge numbers of thousands of
digits, fast multiplication must be implemented.
*/
-int decimal_mul(decimal_t *from1, decimal_t *from2, decimal_t *to)
+int decimal_mul(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
{
int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
@@ -2095,8 +2095,8 @@ int decimal_mul(decimal_t *from1, decima
changed to malloc (or at least fallback to malloc if alloca() fails)
but then, decimal_mul() should be rewritten too :(
*/
-static int do_div_mod(decimal_t *from1, decimal_t *from2,
- decimal_t *to, decimal_t *mod, int scale_incr)
+static int do_div_mod(const decimal_t *from1, const decimal_t *from2,
+ decimal_t *to, decimal_t *mod, int scale_incr)
{
int frac1=ROUND_UP(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1,
frac2=ROUND_UP(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2,
@@ -2181,9 +2181,12 @@ static int do_div_mod(decimal_t *from1,
}
buf0=to->buf;
stop0=buf0+intg0+frac0;
+ DBUG_ASSERT(stop0 <= &to->buf[to->len]);
if (likely(div_mod))
- while (dintg++ < 0)
+ while (dintg++ < 0 && buf0 < &to->buf[to->len])
+ {
*buf0++=0;
+ }
len1=(i=ROUND_UP(prec1))+ROUND_UP(2*frac2+scale_incr+1) + 1;
set_if_bigger(len1, 3);
@@ -2355,7 +2358,8 @@ done:
*/
int
-decimal_div(decimal_t *from1, decimal_t *from2, decimal_t *to, int scale_incr)
+decimal_div(const decimal_t *from1, const decimal_t *from2, decimal_t *to,
+ int scale_incr)
{
return do_div_mod(from1, from2, to, 0, scale_incr);
}
@@ -2387,7 +2391,7 @@ decimal_div(decimal_t *from1, decimal_t
thus, there's no requirement for M or N to be integers
*/
-int decimal_mod(decimal_t *from1, decimal_t *from2, decimal_t *to)
+int decimal_mod(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
{
return do_div_mod(from1, from2, 0, to, 0);
}
=== modified file 'unittest/gunit/item-t.cc'
--- a/unittest/gunit/item-t.cc 2011-02-21 10:36:31 +0000
+++ b/unittest/gunit/item-t.cc 2011-03-18 12:25:56 +0000
@@ -24,6 +24,59 @@
namespace {
+/*
+ A mock error handler for error_handler_hook.
+*/
+uint expected_error= 0;
+extern "C" void test_error_handler_hook(uint err, const char *str, myf MyFlags)
+{
+ EXPECT_EQ(expected_error, err) << str;
+}
+
+
+/**
+ A mock error handler which registers itself with the THD in the CTOR,
+ and unregisters in the DTOR. The function handle_condition() will
+ verify that it is called with the expected error number.
+ The DTOR will verify that handle_condition() has actually been called.
+*/
+class Mock_error_handler : public Internal_error_handler
+{
+public:
+ Mock_error_handler(THD *thd, uint expected_error)
+ : m_thd(thd),
+ m_expected_error(expected_error),
+ m_handle_called(0)
+ {
+ thd->push_internal_handler(this);
+ }
+
+ virtual ~Mock_error_handler()
+ {
+ // Strange Visual Studio bug: have to store 'this' in local variable.
+ Internal_error_handler *me= this;
+ EXPECT_EQ(me, m_thd->pop_internal_handler());
+ EXPECT_GE(m_handle_called, 0);
+ }
+
+ virtual bool handle_condition(THD *thd,
+ uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ MYSQL_ERROR ** cond_hdl)
+ {
+ EXPECT_EQ(sql_errno, m_expected_error);
+ ++m_handle_called;
+ return true;
+ }
+private:
+ THD *m_thd;
+ uint m_expected_error;
+ int m_handle_called;
+};
+
+
class ItemTest : public ::testing::Test
{
protected:
@@ -39,9 +92,11 @@ protected:
char *argv[] = { my_name, 0 };
set_remaining_args(1, argv);
init_common_variables();
+ my_init_signals();
randominit(&sql_rand, 0, 0);
xid_cache_init();
delegates_init();
+ error_handler_hook= test_error_handler_hook;
}
static void TearDownTestCase()
@@ -54,10 +109,12 @@ protected:
virtual void SetUp()
{
+ expected_error= 0;
m_thd= new THD(false);
THD *stack_thd= m_thd;
m_thd->thread_stack= (char*) &stack_thd;
m_thd->store_globals();
+ lex_start(m_thd);
}
virtual void TearDown()
@@ -66,7 +123,7 @@ protected:
delete m_thd;
}
- THD *m_thd;
+ THD *m_thd;
};
@@ -189,6 +246,38 @@ TEST_F(ItemTest, ItemFuncDesDecrypt)
}
+TEST_F(ItemTest, ItemFuncIntDivOverflow)
+{
+ const char dividend_str[]=
+ "99999999999999999999999999999999999999999"
+ "99999999999999999999999999999999999999999";
+ const char divisor_str[]= "0.5";
+ Item_float *dividend= new Item_float(dividend_str, sizeof(dividend_str));
+ Item_float *divisor= new Item_float(divisor_str, sizeof(divisor_str));
+ Item_func_int_div* quotient= new Item_func_int_div(dividend, divisor);
+
+ Mock_error_handler error_handler(m_thd, ER_TRUNCATED_WRONG_VALUE);
+ EXPECT_FALSE(quotient->fix_fields(m_thd, NULL));
+ expected_error= ER_DATA_OUT_OF_RANGE;
+ quotient->val_int();
+}
+
+
+TEST_F(ItemTest, ItemFuncIntDivUnderflow)
+{
+ // Bug #11792200 - DIVIDING LARGE NUMBERS CAUSES STACK CORRUPTIONS
+ const char dividend_str[]= "1.175494351E-37";
+ const char divisor_str[]= "1.7976931348623157E+308";
+ Item_float *dividend= new Item_float(dividend_str, sizeof(dividend_str));
+ Item_float *divisor= new Item_float(divisor_str, sizeof(divisor_str));
+ Item_func_int_div* quotient= new Item_func_int_div(dividend, divisor);
+
+ Mock_error_handler error_handler(m_thd, ER_TRUNCATED_WRONG_VALUE);
+ EXPECT_FALSE(quotient->fix_fields(m_thd, NULL));
+ EXPECT_EQ(0, quotient->val_int());
+}
+
+
/*
This is not an exhaustive test. It simply demonstrates that more of the
initializations in mysqld.cc are needed for testing Item_xxx classes.
No bundle (reason: useless for push emails).
| Thread |
|---|
| • bzr push into mysql-trunk branch (tor.didriksen:3300) | Tor Didriksen | 18 Mar |