Commit 3ad228d7 authored by Davi Arnaut's avatar Davi Arnaut

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.
parent 017307f2
...@@ -111,3 +111,6 @@ set @a=-14632475938453979136; ...@@ -111,3 +111,6 @@ set @a=-14632475938453979136;
execute s using @a, @a; execute s using @a, @a;
ERROR HY000: Incorrect arguments to EXECUTE ERROR HY000: Incorrect arguments to EXECUTE
End of 5.0 tests End of 5.0 tests
select 1 as a limit 4294967296,10;
a
End of 5.1 tests
...@@ -95,3 +95,11 @@ set @a=-14632475938453979136; ...@@ -95,3 +95,11 @@ set @a=-14632475938453979136;
execute s using @a, @a; execute s using @a, @a;
--echo End of 5.0 tests --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
...@@ -2041,12 +2041,26 @@ st_lex::copy_db_to(char **p_db, uint *p_db_length) const ...@@ -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) void st_select_lex_unit::set_limit(SELECT_LEX *sl)
{ {
ha_rows select_limit_val; ha_rows select_limit_val;
ulonglong val;
DBUG_ASSERT(! thd->stmt_arena->is_stmt_prepare()); DBUG_ASSERT(! thd->stmt_arena->is_stmt_prepare());
select_limit_val= (ha_rows)(sl->select_limit ? sl->select_limit->val_uint() : val= sl->select_limit ? sl->select_limit->val_uint() : HA_POS_ERROR;
HA_POS_ERROR); select_limit_val= (ha_rows)val;
offset_limit_cnt= (ha_rows)(sl->offset_limit ? sl->offset_limit->val_uint() : #ifndef BIG_TABLES
ULL(0)); /*
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; select_limit_cnt= select_limit_val + offset_limit_cnt;
if (select_limit_cnt < select_limit_val) if (select_limit_cnt < select_limit_val)
select_limit_cnt= HA_POS_ERROR; // no limit select_limit_cnt= HA_POS_ERROR; // no limit
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment