From 5effa05d3f31971461da851f0650951e1e488421 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 19 Jan 2007 18:34:09 +0300 Subject: [PATCH] Bug#25172: Not checked buffer size leads to a server crash. After fix for bug#21798 JOIN stores the pointer to the buffer for sorting fields. It is used while sorting for grouping and for ordering. If ORDER BY clause has more elements then the GROUP BY clause then a memory overrun occurs. Now the length of the ORDER BY list is always passed to the make_unireg_sortorder() function and it allocates buffer big enough to be used for bigger list. sql/sql_delete.cc: Bug#25172: Not checked buffer size leads to a server crash. Length parameter is initialized to 0 for the make_unireg_sortorder() function. sql/sql_select.cc: Bug#25172: Not checked buffer size leads to a server crash. Now the length of the ORDER BY list is always passed to the make_unireg_sortorder() function and it allocates buffer big enough to be used for bigger list. sql/sql_table.cc: Bug#25172: Not checked buffer size leads to a server crash. Length parameter is initialized to 0 for the make_unireg_sortorder() function. sql/sql_update.cc: Bug#25172: Not checked buffer size leads to a server crash. Length parameter is initialized to 0 for the make_unireg_sortorder() function. mysql-test/r/select.result: Added a test case for bug#25172: Not checked buffer size leads to a server crash. mysql-test/t/select.test: Added a test case for bug#25172: Not checked buffer size leads to a server crash. --- mysql-test/r/select.result | 8 ++++++++ mysql-test/t/select.test | 11 +++++++++++ sql/sql_delete.cc | 2 +- sql/sql_select.cc | 12 ++++++++---- sql/sql_table.cc | 2 +- sql/sql_update.cc | 2 +- 6 files changed, 30 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 44063c1e890..d890510ee67 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -3611,3 +3611,11 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 range si,ai si 5 NULL 2 Using where 1 SIMPLE t3 eq_ref PRIMARY,ci PRIMARY 4 test.t2.a 1 Using where DROP TABLE t1,t2,t3; +CREATE TABLE t1 ( f1 int primary key, f2 int, f3 int, f4 int, f5 int, f6 int, checked_out int); +CREATE TABLE t2 ( f11 int PRIMARY KEY ); +INSERT INTO t1 VALUES (1,1,1,0,0,0,0),(2,1,1,3,8,1,0),(3,1,1,4,12,1,0); +INSERT INTO t2 VALUES (62); +SELECT * FROM t1 LEFT JOIN t2 ON f11 = t1.checked_out GROUP BY f1 ORDER BY f2, f3, f4, f5 LIMIT 0, 1; +f1 f2 f3 f4 f5 f6 checked_out f11 +1 1 1 0 0 0 0 NULL +DROP TABLE t1, t2; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 0c82cef867f..5288151f330 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -3092,3 +3092,14 @@ SELECT t3.a FROM t1,t2,t3 t3.c IN ('bb','ee'); DROP TABLE t1,t2,t3; + +# +# Bug#25172: Not checked buffer size leads to a server crash +# +CREATE TABLE t1 ( f1 int primary key, f2 int, f3 int, f4 int, f5 int, f6 int, checked_out int); +CREATE TABLE t2 ( f11 int PRIMARY KEY ); +INSERT INTO t1 VALUES (1,1,1,0,0,0,0),(2,1,1,3,8,1,0),(3,1,1,4,12,1,0); +INSERT INTO t2 VALUES (62); +SELECT * FROM t1 LEFT JOIN t2 ON f11 = t1.checked_out GROUP BY f1 ORDER BY f2, f3, f4, f5 LIMIT 0, 1; +DROP TABLE t1, t2; + diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 7752ac80adb..e8291edda5d 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -142,7 +142,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, if (order && order->elements) { - uint length; + uint length= 0; SORT_FIELD *sortorder; TABLE_LIST tables; List fields; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 93b29c05fd5..b03c4556279 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -12262,7 +12262,7 @@ static int create_sort_index(THD *thd, JOIN *join, ORDER *order, ha_rows filesort_limit, ha_rows select_limit) { - uint length; + uint length= 0; ha_rows examined_rows; TABLE *table; SQL_SELECT *select; @@ -12283,8 +12283,10 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order, !(join->select_options & SELECT_BIG_RESULT)) && test_if_skip_sort_order(tab,order,select_limit,0)) DBUG_RETURN(0); + for (ORDER *ord= join->order; ord; ord= ord->next) + length++; if (!(join->sortorder= - make_unireg_sortorder(order,&length,join->sortorder))) + make_unireg_sortorder(order, &length, join->sortorder))) goto err; /* purecov: inspected */ table->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE), @@ -12690,8 +12692,10 @@ SORT_FIELD *make_unireg_sortorder(ORDER *order, uint *length, for (ORDER *tmp = order; tmp; tmp=tmp->next) count++; if (!sortorder) - sortorder= (SORT_FIELD*) sql_alloc(sizeof(SORT_FIELD)*(count+1)); - pos=sort=sortorder; + sortorder= (SORT_FIELD*) sql_alloc(sizeof(SORT_FIELD) * + (max(count, *length) + 1)); + pos= sort= sortorder; + if (!pos) return 0; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index b3bd3182a59..fd52b9becf6 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3883,7 +3883,7 @@ copy_data_between_tables(TABLE *from,TABLE *to, Copy_field *copy,*copy_end; ulong found_count,delete_count; THD *thd= current_thd; - uint length; + uint length= 0; SORT_FIELD *sortorder; READ_RECORD info; TABLE_LIST tables; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index abffd704188..76d4847f923 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -304,7 +304,7 @@ int mysql_update(THD *thd, Doing an ORDER BY; Let filesort find and sort the rows we are going to update */ - uint length; + uint length= 0; SORT_FIELD *sortorder; ha_rows examined_rows;