Below is the list of changes that have just been committed into a local
5.1 repository of kaa. When kaa does a push these changes
will be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2008-02-19 19:48:24+03:00, kaa@kaamos.(none) +9 -0
Fix for bug #31236: Inconsistent division by zero behavior for
floating point numbers
Some math functions did not check if the result is a valid number
(i.e. neither of +-inf or nan).
Fixed by validating the result where necessary and returning NULL in
case of invalid result.
BitKeeper/deleted/.del-matherr.c@stripped, 2008-02-19 19:46:03+03:00, kaa@kaamos.(none) +0 -0
Rename: sql/matherr.c -> BitKeeper/deleted/.del-matherr.c
configure.in@stripped, 2008-02-19 19:48:22+03:00, kaa@kaamos.(none) +2 -2
Removed DONT_USE_FINITE, it is not used anywhere.
include/my_global.h@stripped, 2008-02-19 19:48:22+03:00, kaa@kaamos.(none) +7 -6
isfinite() is a C99 macro which absoletes finite(). First try to use
it, then fall back to finite() if the target platform has it,
otherwise use our own implementation.
mysql-test/r/func_math.result@stripped, 2008-02-19 19:48:22+03:00, kaa@kaamos.(none) +19 -0
Added a test case for bug #31236.
mysql-test/t/func_math.test@stripped, 2008-02-19 19:48:22+03:00, kaa@kaamos.(none) +13 -1
Added a test case for bug #31236.
sql/field.cc@stripped, 2008-02-19 19:48:22+03:00, kaa@kaamos.(none) +1 -3
No need to check if the finite() or its equivalent is available.
sql/item_func.cc@stripped, 2008-02-19 19:48:22+03:00, kaa@kaamos.(none) +12 -12
Use fix_result() wherever the result can be one of +-inf or nan,
assuming the function arguments are valid numbers.
Removed fix_result() from functions that are defined for all possible
input numbers.
sql/item_func.h@stripped, 2008-02-19 19:48:22+03:00, kaa@kaamos.(none) +7 -12
Moved fix_result() from Item_dec_func to Item_func which is a common
ancestor for Item_dec_func and Item_num_op.
sql/unireg.h@stripped, 2008-02-19 19:48:22+03:00, kaa@kaamos.(none) +0 -1
Removed POSTFIX_ERROR because no code returns it.
diff -Nrup a/configure.in b/configure.in
--- a/configure.in 2007-12-14 20:03:30 +03:00
+++ b/configure.in 2008-02-19 19:48:22 +03:00
@@ -991,8 +991,8 @@ case $SYSTEM_TYPE in
;;
*hpux11.*)
AC_MSG_WARN([Enabling workarounds for hpux 11])
- CFLAGS="$CFLAGS -DHPUX11 -DSNPRINTF_RETURN_TRUNC -DHAVE_BROKEN_PREAD
-DDONT_USE_FINITE -DHAVE_BROKEN_GETPASS -DNO_FCNTL_NONBLOCK
-DDO_NOT_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT"
- CXXFLAGS="$CXXFLAGS -DHPUX11 -DSNPRINTF_RETURN_TRUNC -DHAVE_BROKEN_PREAD
-DDONT_USE_FINITE -D_INCLUDE_LONGLONG -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS
-DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT"
+ CFLAGS="$CFLAGS -DHPUX11 -DSNPRINTF_RETURN_TRUNC -DHAVE_BROKEN_PREAD
-DHAVE_BROKEN_GETPASS -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS
-DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT"
+ CXXFLAGS="$CXXFLAGS -DHPUX11 -DSNPRINTF_RETURN_TRUNC -DHAVE_BROKEN_PREAD
-D_INCLUDE_LONGLONG -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS
-DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT"
if test "$with_named_thread" = "no"
then
AC_MSG_WARN([Using --with-named-thread=-lpthread])
diff -Nrup a/include/my_global.h b/include/my_global.h
--- a/include/my_global.h 2007-11-30 03:38:25 +03:00
+++ b/include/my_global.h 2008-02-19 19:48:22 +03:00
@@ -486,9 +486,6 @@ C_MODE_END
#include <sys/stream.h> /* HPUX 10.20 defines ulong here. UGLY !!! */
#define HAVE_ULONG
#endif
-#ifdef DONT_USE_FINITE /* HPUX 11.x has is_finite() */
-#undef HAVE_FINITE
-#endif
#if defined(HPUX10) && defined(_LARGEFILE64_SOURCE) && defined(THREAD)
/* Fix bug in setrlimit */
#undef setrlimit
@@ -858,9 +855,13 @@ typedef SOCKET_SIZE_TYPE size_socket;
#define SIZE_T_MAX ~((size_t) 0)
#endif
-#ifndef HAVE_FINITE
+#ifndef isfinite
+#ifdef HAVE_FINITE
+#define isfinite(x) finite(x)
+#else
#define finite(x) (1.0 / fabs(x) > 0.0)
-#endif
+#endif /* HAVE_FINITE */
+#endif /* isfinite */
#ifndef HAVE_ISNAN
#define isnan(x) ((x) != (x))
@@ -870,7 +871,7 @@ typedef SOCKET_SIZE_TYPE size_socket;
/* isinf() can be used in both C and C++ code */
#define my_isinf(X) isinf(X)
#else
-#define my_isinf(X) (!finite(X) && !isnan(X))
+#define my_isinf(X) (!isfinite(X) && !isnan(X))
#endif
/* Define missing math constants. */
diff -Nrup a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result
--- a/mysql-test/r/func_math.result 2007-10-04 16:10:54 +04:00
+++ b/mysql-test/r/func_math.result 2008-02-19 19:48:22 +03:00
@@ -408,3 +408,22 @@ a DIV 2
0
DROP TABLE t1;
End of 5.0 tests
+SELECT 1e308 + 1e308;
+1e308 + 1e308
+NULL
+SELECT -1e308 - 1e308;
+-1e308 - 1e308
+NULL
+SELECT 1e300 * 1e300;
+1e300 * 1e300
+NULL
+SELECT 1e300 / 1e-300;
+1e300 / 1e-300
+NULL
+SELECT EXP(750);
+EXP(750)
+NULL
+SELECT POW(10, 309);
+POW(10, 309)
+NULL
+End of 5.1 tests
diff -Nrup a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test
--- a/mysql-test/t/func_math.test 2007-10-04 16:10:54 +04:00
+++ b/mysql-test/t/func_math.test 2008-02-19 19:48:22 +03:00
@@ -248,5 +248,17 @@ INSERT INTO t1 VALUES ('a');
SELECT a DIV 2 FROM t1 UNION SELECT a DIV 2 FROM t1;
DROP TABLE t1;
-
--echo End of 5.0 tests
+
+#
+# Bug #31236: Inconsistent division by zero behavior for floating point numbers
+#
+
+SELECT 1e308 + 1e308;
+SELECT -1e308 - 1e308;
+SELECT 1e300 * 1e300;
+SELECT 1e300 / 1e-300;
+SELECT EXP(750);
+SELECT POW(10, 309);
+
+--echo End of 5.1 tests
diff -Nrup a/sql/field.cc b/sql/field.cc
--- a/sql/field.cc 2008-01-10 13:46:31 +03:00
+++ b/sql/field.cc 2008-02-19 19:48:22 +03:00
@@ -2263,13 +2263,11 @@ int Field_decimal::store(double nr)
return 1;
}
-#ifdef HAVE_FINITE
- if (!finite(nr)) // Handle infinity as special case
+ if (!isfinite(nr)) // Handle infinity as special case
{
overflow(nr < 0.0);
return 1;
}
-#endif
reg4 uint i;
size_t length;
diff -Nrup a/sql/item_func.cc b/sql/item_func.cc
--- a/sql/item_func.cc 2008-01-19 20:59:07 +03:00
+++ b/sql/item_func.cc 2008-02-19 19:48:22 +03:00
@@ -1104,7 +1104,7 @@ double Item_func_plus::real_op()
double value= args[0]->val_real() + args[1]->val_real();
if ((null_value=args[0]->null_value || args[1]->null_value))
return 0.0;
- return value;
+ return fix_result(value);
}
@@ -1186,7 +1186,7 @@ double Item_func_minus::real_op()
double value= args[0]->val_real() - args[1]->val_real();
if ((null_value=args[0]->null_value || args[1]->null_value))
return 0.0;
- return value;
+ return fix_result(value);
}
@@ -1224,7 +1224,7 @@ double Item_func_mul::real_op()
double value= args[0]->val_real() * args[1]->val_real();
if ((null_value=args[0]->null_value || args[1]->null_value))
return 0.0;
- return value;
+ return fix_result(value);
}
@@ -1282,7 +1282,7 @@ double Item_func_div::real_op()
signal_divide_by_null();
return 0.0;
}
- return value/val2;
+ return fix_result(value/val2);
}
@@ -1655,7 +1655,7 @@ double Item_func_exp::val_real()
double value= args[0]->val_real();
if ((null_value=args[0]->null_value))
return 0.0; /* purecov: inspected */
- return exp(value);
+ return fix_result(exp(value));
}
double Item_func_sqrt::val_real()
@@ -1674,7 +1674,7 @@ double Item_func_pow::val_real()
double val2= args[1]->val_real();
if ((null_value=(args[0]->null_value || args[1]->null_value)))
return 0.0; /* purecov: inspected */
- return pow(value,val2);
+ return fix_result(pow(value,val2));
}
// Trigonometric functions
@@ -1686,7 +1686,7 @@ double Item_func_acos::val_real()
volatile double value= args[0]->val_real();
if ((null_value=(args[0]->null_value || (value < -1.0 || value > 1.0))))
return 0.0;
- return fix_result(acos(value));
+ return acos(value);
}
double Item_func_asin::val_real()
@@ -1696,7 +1696,7 @@ double Item_func_asin::val_real()
volatile double value= args[0]->val_real();
if ((null_value=(args[0]->null_value || (value < -1.0 || value > 1.0))))
return 0.0;
- return fix_result(asin(value));
+ return asin(value);
}
double Item_func_atan::val_real()
@@ -1710,9 +1710,9 @@ double Item_func_atan::val_real()
double val2= args[1]->val_real();
if ((null_value=args[1]->null_value))
return 0.0;
- return fix_result(atan2(value,val2));
+ return atan2(value,val2);
}
- return fix_result(atan(value));
+ return atan(value);
}
double Item_func_cos::val_real()
@@ -1721,7 +1721,7 @@ double Item_func_cos::val_real()
double value= args[0]->val_real();
if ((null_value=args[0]->null_value))
return 0.0;
- return fix_result(cos(value));
+ return cos(value);
}
double Item_func_sin::val_real()
@@ -1730,7 +1730,7 @@ double Item_func_sin::val_real()
double value= args[0]->val_real();
if ((null_value=args[0]->null_value))
return 0.0;
- return fix_result(sin(value));
+ return sin(value);
}
double Item_func_tan::val_real()
diff -Nrup a/sql/item_func.h b/sql/item_func.h
--- a/sql/item_func.h 2007-12-13 14:57:03 +03:00
+++ b/sql/item_func.h 2008-02-19 19:48:22 +03:00
@@ -192,6 +192,13 @@ public:
void * arg, traverse_order order);
bool is_expensive_processor(uchar *arg);
virtual bool is_expensive() { return 0; }
+ inline double fix_result(double value)
+ {
+ if (isfinite(value))
+ return value;
+ null_value=1;
+ return 0.0;
+ }
};
@@ -498,18 +505,6 @@ class Item_dec_func :public Item_real_fu
{
decimals=NOT_FIXED_DEC; max_length=float_length(decimals);
maybe_null=1;
- }
- inline double fix_result(double value)
- {
-#ifndef HAVE_FINITE
- return value;
-#else
- /* The following should be safe, even if we compare doubles */
- if (finite(value) && value != POSTFIX_ERROR)
- return value;
- null_value=1;
- return 0.0;
-#endif
}
};
diff -Nrup a/sql/matherr.c b/sql/matherr.c
--- a/sql/matherr.c 2006-12-30 23:02:07 +03:00
+++ /dev/null Wed Dec 31 16:00:00 196900
@@ -1,42 +0,0 @@
-/* Copyright (C) 2000-2001 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Fix that we got POSTFIX_ERROR when doing unreasonable math (not core) */
-
-#include <my_global.h>
-#include <errno.h>
-
- /* Fix that we gets POSTFIX_ERROR when error in math */
-
-#if defined(HAVE_MATHERR)
-int matherr(struct exception *x)
-{
- if (x->type != PLOSS)
- x->retval=POSTFIX_ERROR;
- switch (x->type) {
- case DOMAIN:
- case SING:
- my_errno=EDOM;
- break;
- case OVERFLOW:
- case UNDERFLOW:
- my_errno=ERANGE;
- break;
- default:
- break;
- }
- return(1); /* Take no other action */
-}
-#endif
diff -Nrup a/sql/unireg.h b/sql/unireg.h
--- a/sql/unireg.h 2007-09-10 15:16:01 +04:00
+++ b/sql/unireg.h 2008-02-19 19:48:22 +03:00
@@ -108,7 +108,6 @@
#define READ_RECORD_BUFFER (uint) (IO_SIZE*8) /* Pointer_buffer_size */
#define DISK_BUFFER_SIZE (uint) (IO_SIZE*16) /* Size of diskbuffer */
-#define POSTFIX_ERROR DBL_MAX
#define ME_INFO (ME_HOLDTANG+ME_OLDWIN+ME_NOREFRESH)
#define ME_ERROR (ME_BELL+ME_OLDWIN+ME_NOREFRESH)
| Thread |
|---|
| • bk commit into 5.1 tree (kaa:1.2659) BUG#31236 | Alexey Kopytov | 19 Feb 2008 |