From c2abf960f917184084fb0143aaa07d707dc5ff6d Mon Sep 17 00:00:00 2001 From: "gkodinov/kgeorge@magare.gmz" <> Date: Wed, 19 Sep 2007 17:47:52 +0300 Subject: [PATCH] Bug #30639: limit offset,rowcount wraps when rowcount >= 2^32 in windows The parser uses ulonglong to store the LIMIT number. This number then is stored into a variable of type ha_rows. ha_rows is either 4 or 8 byte depending on the BIG_TABLES define from config.h So an overflow may occur (and LIMIT becomes zero) while storing an ulonglong value in ha_rows. Fixed by : 1. Using the maximum possible value for ha_rows on overflow 2. Defining BIG_TABLES for the windows builds (to match the others) --- include/config-win.h | 2 ++ mysql-test/r/select.result | 17 +++++++++++++++++ mysql-test/t/select.test | 10 ++++++++++ sql/sql_lex.cc | 13 +++++++++++-- 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/include/config-win.h b/include/config-win.h index bc2ae60f137..2e64e165630 100644 --- a/include/config-win.h +++ b/include/config-win.h @@ -15,6 +15,8 @@ /* Defines for Win32 to make it compatible for MySQL */ +#define BIG_TABLES + #ifdef __WIN2000__ /* We have to do this define before including windows.h to get the AWE API functions */ diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 48e8bf933e1..4a75937410c 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -4048,3 +4048,20 @@ Level Code Message Note 1003 select '0' AS `c1` from `test`.`t1` `join_0` join `test`.`t1` `join_1` join `test`.`t1` `join_2` join `test`.`t1` `join_3` join `test`.`t1` `join_4` join `test`.`t1` `join_5` join `test`.`t1` `join_6` join `test`.`t1` `join_7` where 0 group by '0','0','0','0','0' DROP TABLE t1; End of 5.0 tests +create table t1(a INT, KEY (a)); +INSERT INTO t1 VALUES (1),(2),(3),(4),(5); +SELECT a FROM t1 ORDER BY a LIMIT 2; +a +1 +2 +SELECT a FROM t1 ORDER BY a LIMIT 2,4294967296; +a +3 +4 +5 +SELECT a FROM t1 ORDER BY a LIMIT 2,4294967297; +a +3 +4 +5 +DROP TABLE t1; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 3f17eb92d40..59670dddac5 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -3450,3 +3450,13 @@ SHOW WARNINGS; DROP TABLE t1; --echo End of 5.0 tests + +# +# Bug #30639: limit offset,rowcount wraps when rowcount >= 2^32 in windows +# +create table t1(a INT, KEY (a)); +INSERT INTO t1 VALUES (1),(2),(3),(4),(5); +SELECT a FROM t1 ORDER BY a LIMIT 2; +SELECT a FROM t1 ORDER BY a LIMIT 2,4294967296; +SELECT a FROM t1 ORDER BY a LIMIT 2,4294967297; +DROP TABLE t1; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 66f5540d286..56bdaf6e4c5 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -2372,10 +2372,19 @@ st_lex::copy_db_to(char **p_db, size_t *p_db_length) const void st_select_lex_unit::set_limit(st_select_lex *sl) { ha_rows select_limit_val; + ulonglong val; DBUG_ASSERT(! thd->stmt_arena->is_stmt_prepare()); - select_limit_val= (ha_rows)(sl->select_limit ? sl->select_limit->val_uint() : - HA_POS_ERROR); + val= sl->select_limit ? sl->select_limit->val_uint() : HA_POS_ERROR; + select_limit_val= (ha_rows)val; +#ifndef BIG_TABLES + /* + Check for overflow : ha_rows can be smaller then ulonglong if + BIG_TABLES is off. + */ + if (val != (ulonglong)select_limit_val) + select_limit_val= HA_POS_ERROR; +#endif offset_limit_cnt= (ha_rows)(sl->offset_limit ? sl->offset_limit->val_uint() : ULL(0)); select_limit_cnt= select_limit_val + offset_limit_cnt;