summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavi Arnaut <Davi.Arnaut@Sun.COM>2008-10-15 18:34:51 -0300
committerDavi Arnaut <Davi.Arnaut@Sun.COM>2008-10-15 18:34:51 -0300
commit3ad228d7fba6fa2e5b98569f798583b8f8b90db9 (patch)
tree7bffc9fc29b23db812377eacd41db43c69d03850
parent017307f2163a068520374b3083895e246b7a4a60 (diff)
downloadmariadb-git-3ad228d7fba6fa2e5b98569f798583b8f8b90db9.tar.gz
Bug#37075: offset of limit clause might be truncated on 32-bits server w/o big tables
The problem is that the offset argument of the limit clause might be truncated on a 32-bits server built without big tables support. The truncation was happening because the original 64-bits long argument was being cast to a 32-bits (ha_rows) offset counter. The solution is to check if the conversing resulted in value truncation and if so, the offset is set to the maximum possible value that can fit on the type. mysql-test/r/limit.result: Add test case result for Bug#37075 mysql-test/t/limit.test: Add test case for Bug#37075 sql/sql_lex.cc: Check for truncation of the offset value. If value was truncated, set to the maximum possible value.
-rw-r--r--mysql-test/r/limit.result3
-rw-r--r--mysql-test/t/limit.test8
-rw-r--r--sql/sql_lex.cc22
3 files changed, 29 insertions, 4 deletions
diff --git a/mysql-test/r/limit.result b/mysql-test/r/limit.result
index 2acf74162a4..caed588acdb 100644
--- a/mysql-test/r/limit.result
+++ b/mysql-test/r/limit.result
@@ -111,3 +111,6 @@ set @a=-14632475938453979136;
execute s using @a, @a;
ERROR HY000: Incorrect arguments to EXECUTE
End of 5.0 tests
+select 1 as a limit 4294967296,10;
+a
+End of 5.1 tests
diff --git a/mysql-test/t/limit.test b/mysql-test/t/limit.test
index 9cccca1adc3..5847b90367a 100644
--- a/mysql-test/t/limit.test
+++ b/mysql-test/t/limit.test
@@ -95,3 +95,11 @@ set @a=-14632475938453979136;
execute s using @a, @a;
--echo End of 5.0 tests
+
+#
+# Bug#37075: offset of limit clause might be truncated to 0 on 32-bits server w/o big tables
+#
+
+select 1 as a limit 4294967296,10;
+
+--echo End of 5.1 tests
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index ba9c0e93134..71aa80b8170 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -2041,12 +2041,26 @@ st_lex::copy_db_to(char **p_db, uint *p_db_length) const
void st_select_lex_unit::set_limit(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);
- offset_limit_cnt= (ha_rows)(sl->offset_limit ? sl->offset_limit->val_uint() :
- ULL(0));
+ 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
+ val= sl->offset_limit ? sl->offset_limit->val_uint() : ULL(0);
+ offset_limit_cnt= (ha_rows)val;
+#ifndef BIG_TABLES
+ /* Check for truncation. */
+ if (val != (ulonglong)offset_limit_cnt)
+ offset_limit_cnt= HA_POS_ERROR;
+#endif
select_limit_cnt= select_limit_val + offset_limit_cnt;
if (select_limit_cnt < select_limit_val)
select_limit_cnt= HA_POS_ERROR; // no limit