Commit 83f19ef4 authored by Karen Langford's avatar Karen Langford

Merge from mysql-5.1.57-release

parents 902e64da 91487367
...@@ -12756,3 +12756,19 @@ a ...@@ -12756,3 +12756,19 @@ a
1 1
2 2
DROP TABLE t1; DROP TABLE t1;
#
# BUG#57162 - valgrind errors, random data when returning
# ordered data from archive tables
#
SET sort_buffer_size=32804;
CREATE TABLE t1(a INT, b CHAR(255), c CHAR(255), d CHAR(255),
e CHAR(255), f INT) ENGINE=ARCHIVE DEFAULT CHARSET utf8;
INSERT INTO t1 VALUES(-1,'b','c','d','e',1);
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT t1.* FROM t1,t1 t2,t1 t3,t1 t4,t1 t5,t1 t6;
SELECT * FROM t1 ORDER BY f LIMIT 1;
a b c d e f
-1 b c d e 1
DROP TABLE t1;
SET sort_buffer_size=DEFAULT;
...@@ -451,4 +451,21 @@ SELECT CONVERT(t2.a USING UTF8) FROM t1, t1 t2 LIMIT 1 ...@@ -451,4 +451,21 @@ SELECT CONVERT(t2.a USING UTF8) FROM t1, t1 t2 LIMIT 1
1 1
1 1
DROP TABLE t1; DROP TABLE t1;
#
# Bug #11765023: 57934: DOS POSSIBLE SINCE BINARY CASTING
# DOESN'T ADHERE TO MAX_ALLOWED_PACKET
SET @@GLOBAL.max_allowed_packet=2048;
Warnings:
Warning 1105 The value of 'max_allowed_packet' should be no less than the value of 'net_buffer_length'
SELECT CONVERT('a', BINARY(2049));
CONVERT('a', BINARY(2049))
NULL
Warnings:
Warning 1301 Result of cast_as_binary() was larger than max_allowed_packet (2048) - truncated
SELECT CONVERT('a', CHAR(2049));
CONVERT('a', CHAR(2049))
NULL
Warnings:
Warning 1301 Result of cast_as_char() was larger than max_allowed_packet (2048) - truncated
SET @@GLOBAL.max_allowed_packet=default;
End of 5.1 tests End of 5.1 tests
...@@ -1040,6 +1040,39 @@ drop table t1; ...@@ -1040,6 +1040,39 @@ drop table t1;
# #
create table t1(a char(32) not null) engine=myisam; create table t1(a char(32) not null) engine=myisam;
create spatial index i on t1 (a); create spatial index i on t1 (a);
ERROR HY000: Can't create table '#sql-temporary' (errno: 140) ERROR HY000: Incorrect arguments to SPATIAL INDEX
drop table t1; drop table t1;
CREATE TABLE t0 (a BINARY(32) NOT NULL);
CREATE SPATIAL INDEX i on t0 (a);
ERROR HY000: Incorrect arguments to SPATIAL INDEX
INSERT INTO t0 VALUES (1);
CREATE TABLE t1(
col0 BINARY NOT NULL,
col2 TIMESTAMP,
SPATIAL INDEX i1 (col0)
) ENGINE=MyISAM;
ERROR HY000: Incorrect arguments to SPATIAL INDEX
CREATE TABLE t1 (
col0 BINARY NOT NULL,
col2 TIMESTAMP
) ENGINE=MyISAM;
CREATE SPATIAL INDEX idx0 ON t1(col0);
ERROR HY000: Incorrect arguments to SPATIAL INDEX
ALTER TABLE t1 ADD SPATIAL INDEX i1 (col0);
ERROR HY000: Incorrect arguments to SPATIAL INDEX
CREATE TABLE t2 (
col0 INTEGER NOT NULL,
col1 POINT,
col2 POINT
);
CREATE SPATIAL INDEX idx0 ON t2 (col1, col2);
ERROR HY000: Incorrect arguments to SPATIAL INDEX
CREATE TABLE t3 (
col0 INTEGER NOT NULL,
col1 POINT,
col2 LINESTRING,
SPATIAL INDEX i1 (col1, col2)
);
ERROR HY000: Incorrect arguments to SPATIAL INDEX
DROP TABLE t0, t1, t2;
End of 5.1 tests End of 5.1 tests
...@@ -1678,3 +1678,18 @@ SELECT * FROM t1; ...@@ -1678,3 +1678,18 @@ SELECT * FROM t1;
REPAIR TABLE t1 EXTENDED; REPAIR TABLE t1 EXTENDED;
SELECT * FROM t1; SELECT * FROM t1;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # BUG#57162 - valgrind errors, random data when returning
--echo # ordered data from archive tables
--echo #
SET sort_buffer_size=32804;
CREATE TABLE t1(a INT, b CHAR(255), c CHAR(255), d CHAR(255),
e CHAR(255), f INT) ENGINE=ARCHIVE DEFAULT CHARSET utf8;
INSERT INTO t1 VALUES(-1,'b','c','d','e',1);
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT t1.* FROM t1,t1 t2,t1 t3,t1 t4,t1 t5,t1 t6;
SELECT * FROM t1 ORDER BY f LIMIT 1;
DROP TABLE t1;
SET sort_buffer_size=DEFAULT;
...@@ -282,5 +282,19 @@ SELECT 1 FROM ...@@ -282,5 +282,19 @@ SELECT 1 FROM
) AS s LIMIT 1; ) AS s LIMIT 1;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # Bug #11765023: 57934: DOS POSSIBLE SINCE BINARY CASTING
--echo # DOESN'T ADHERE TO MAX_ALLOWED_PACKET
SET @@GLOBAL.max_allowed_packet=2048;
# reconnect to make the new max packet size take effect
--connect (newconn, localhost, root,,)
SELECT CONVERT('a', BINARY(2049));
SELECT CONVERT('a', CHAR(2049));
connection default;
disconnect newconn;
SET @@GLOBAL.max_allowed_packet=default;
--echo End of 5.1 tests --echo End of 5.1 tests
...@@ -760,10 +760,56 @@ drop table t1; ...@@ -760,10 +760,56 @@ drop table t1;
--echo # on char > 31 bytes". --echo # on char > 31 bytes".
--echo # --echo #
create table t1(a char(32) not null) engine=myisam; create table t1(a char(32) not null) engine=myisam;
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/ --error ER_WRONG_ARGUMENTS
--error ER_CANT_CREATE_TABLE
create spatial index i on t1 (a); create spatial index i on t1 (a);
drop table t1; drop table t1;
#
# Bug#11767480 - SPATIAL INDEXES ON NON-SPATIAL COLUMNS CAUSE CRASHES.
#
CREATE TABLE t0 (a BINARY(32) NOT NULL);
--error ER_WRONG_ARGUMENTS
CREATE SPATIAL INDEX i on t0 (a);
INSERT INTO t0 VALUES (1);
--error ER_WRONG_ARGUMENTS
CREATE TABLE t1(
col0 BINARY NOT NULL,
col2 TIMESTAMP,
SPATIAL INDEX i1 (col0)
) ENGINE=MyISAM;
# Test other ways to add indices
CREATE TABLE t1 (
col0 BINARY NOT NULL,
col2 TIMESTAMP
) ENGINE=MyISAM;
--error ER_WRONG_ARGUMENTS
CREATE SPATIAL INDEX idx0 ON t1(col0);
--error ER_WRONG_ARGUMENTS
ALTER TABLE t1 ADD SPATIAL INDEX i1 (col0);
CREATE TABLE t2 (
col0 INTEGER NOT NULL,
col1 POINT,
col2 POINT
);
--error ER_WRONG_ARGUMENTS
CREATE SPATIAL INDEX idx0 ON t2 (col1, col2);
--error ER_WRONG_ARGUMENTS
CREATE TABLE t3 (
col0 INTEGER NOT NULL,
col1 POINT,
col2 LINESTRING,
SPATIAL INDEX i1 (col1, col2)
);
# cleanup
DROP TABLE t0, t1, t2;
--echo End of 5.1 tests --echo End of 5.1 tests
...@@ -185,6 +185,7 @@ cp Docs/INSTALL-BINARY $DESTDIR/Docs/ ...@@ -185,6 +185,7 @@ cp Docs/INSTALL-BINARY $DESTDIR/Docs/
cp Docs/manual.chm $DESTDIR/Docs/ || /bin/true cp Docs/manual.chm $DESTDIR/Docs/ || /bin/true
cp ChangeLog $DESTDIR/Docs/ || /bin/true cp ChangeLog $DESTDIR/Docs/ || /bin/true
cp support-files/my-*.ini $DESTDIR/ cp support-files/my-*.ini $DESTDIR/
cp README $DESTDIR/
if [ -f COPYING ] ; then if [ -f COPYING ] ; then
cp COPYING $DESTDIR/ cp COPYING $DESTDIR/
......
...@@ -4476,7 +4476,8 @@ int ha_partition::index_read_idx_map(uchar *buf, uint index, ...@@ -4476,7 +4476,8 @@ int ha_partition::index_read_idx_map(uchar *buf, uint index,
break; break;
} }
} }
m_last_part= part; if (part <= m_part_spec.end_part)
m_last_part= part;
} }
else else
{ {
...@@ -6396,7 +6397,14 @@ void ha_partition::print_error(int error, myf errflag) ...@@ -6396,7 +6397,14 @@ void ha_partition::print_error(int error, myf errflag)
{ {
/* In case m_file has not been initialized, like in bug#42438 */ /* In case m_file has not been initialized, like in bug#42438 */
if (m_file) if (m_file)
{
if (m_last_part >= m_tot_parts)
{
DBUG_ASSERT(0);
m_last_part= 0;
}
m_file[m_last_part]->print_error(error, errflag); m_file[m_last_part]->print_error(error, errflag);
}
else else
handler::print_error(error, errflag); handler::print_error(error, errflag);
} }
......
...@@ -2444,6 +2444,19 @@ String *Item_char_typecast::val_str(String *str) ...@@ -2444,6 +2444,19 @@ String *Item_char_typecast::val_str(String *str)
String *res; String *res;
uint32 length; uint32 length;
if (cast_length >= 0 &&
((unsigned) cast_length) > current_thd->variables.max_allowed_packet)
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_ALLOWED_PACKET_OVERFLOWED,
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
cast_cs == &my_charset_bin ?
"cast_as_binary" : func_name(),
current_thd->variables.max_allowed_packet);
null_value= 1;
return 0;
}
if (!charset_conversion) if (!charset_conversion)
{ {
if (!(res= args[0]->val_str(str))) if (!(res= args[0]->val_str(str)))
......
...@@ -653,6 +653,94 @@ bool init_new_connection_handler_thread() ...@@ -653,6 +653,94 @@ bool init_new_connection_handler_thread()
return 0; return 0;
} }
#ifndef EMBEDDED_LIBRARY
/**
Get a null character terminated string from a user-supplied buffer.
@param buffer[in, out] Pointer to the buffer to be scanned.
@param max_bytes_available[in, out] Limit the bytes to scan.
@param string_length[out] The number of characters scanned not including
the null character.
@remark The string_length does not include the terminating null character.
However, after the call, the buffer is increased by string_length+1
bytes, beyond the null character if there still available bytes to
scan.
@return pointer to beginning of the string scanned.
@retval NULL The buffer content is malformed
*/
static
char *get_null_terminated_string(char **buffer,
size_t *max_bytes_available,
size_t *string_length)
{
char *str= (char *)memchr(*buffer, '\0', *max_bytes_available);
if (str == NULL)
return NULL;
*string_length= (size_t)(str - *buffer);
*max_bytes_available-= *string_length + 1;
str= *buffer;
*buffer += *string_length + 1;
return str;
}
/**
Get a length encoded string from a user-supplied buffer.
@param buffer[in, out] The buffer to scan; updates position after scan.
@param max_bytes_available[in, out] Limit the number of bytes to scan
@param string_length[out] Number of characters scanned
@remark In case the length is zero, then the total size of the string is
considered to be 1 byte; the size byte.
@return pointer to first byte after the header in buffer.
@retval NULL The buffer content is malformed
*/
static
char *get_length_encoded_string(char **buffer,
size_t *max_bytes_available,
size_t *string_length)
{
if (*max_bytes_available == 0)
return NULL;
/* Do double cast to prevent overflow from signed / unsigned conversion */
size_t str_len= (size_t)(unsigned char)**buffer;
/*
If the length encoded string has the length 0
the total size of the string is only one byte long (the size byte)
*/
if (str_len == 0)
{
++*buffer;
*string_length= 0;
/*
Return a pointer to the 0 character so the return value will be
an empty string.
*/
return *buffer-1;
}
if (str_len >= *max_bytes_available)
return NULL;
char *str= *buffer+1;
*string_length= str_len;
*max_bytes_available-= *string_length + 1;
*buffer+= *string_length + 1;
return str;
}
/* /*
Perform handshake, authorize client and update thd ACL variables. Perform handshake, authorize client and update thd ACL variables.
...@@ -666,7 +754,6 @@ bool init_new_connection_handler_thread() ...@@ -666,7 +754,6 @@ bool init_new_connection_handler_thread()
> 0 error code (not sent to user) > 0 error code (not sent to user)
*/ */
#ifndef EMBEDDED_LIBRARY
static int check_connection(THD *thd) static int check_connection(THD *thd)
{ {
uint connect_errors= 0; uint connect_errors= 0;
...@@ -855,7 +942,7 @@ static int check_connection(THD *thd) ...@@ -855,7 +942,7 @@ static int check_connection(THD *thd)
} }
#endif /* HAVE_OPENSSL */ #endif /* HAVE_OPENSSL */
if (end >= (char*) net->read_pos+ pkt_len +2) if (end > (char *)net->read_pos + pkt_len)
{ {
inc_host_errors(&thd->remote.sin_addr); inc_host_errors(&thd->remote.sin_addr);
my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip); my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
...@@ -867,39 +954,75 @@ static int check_connection(THD *thd) ...@@ -867,39 +954,75 @@ static int check_connection(THD *thd)
if ((thd->client_capabilities & CLIENT_TRANSACTIONS) && if ((thd->client_capabilities & CLIENT_TRANSACTIONS) &&
opt_using_transactions) opt_using_transactions)
net->return_status= &thd->server_status; net->return_status= &thd->server_status;
/*
In order to safely scan a head for '\0' string terminators
we must keep track of how many bytes remain in the allocated
buffer or we might read past the end of the buffer.
*/
size_t bytes_remaining_in_packet= pkt_len - (end - (char *)net->read_pos);
char *user= end; size_t user_len;
char *passwd= strend(user)+1; char *user= get_null_terminated_string(&end, &bytes_remaining_in_packet,
uint user_len= passwd - user - 1; &user_len);
char *db= passwd; if (user == NULL)
char db_buff[NAME_LEN + 1]; // buffer to store db in utf8 {
char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8 inc_host_errors(&thd->remote.sin_addr);
uint dummy_errors; my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
return 1;
}
/* /*
Old clients send null-terminated string as password; new clients send Old clients send a null-terminated string as password; new clients send
the size (1 byte) + string (not null-terminated). Hence in case of empty the size (1 byte) + string (not null-terminated). Hence in case of empty
password both send '\0'. password both send '\0'.
*/
size_t passwd_len= 0;
char *passwd= NULL;
This strlen() can't be easily deleted without changing protocol. if (thd->client_capabilities & CLIENT_SECURE_CONNECTION)
{
/*
4.1+ password. First byte is password length.
*/
passwd= get_length_encoded_string(&end, &bytes_remaining_in_packet,
&passwd_len);
}
else
{
/*
Old passwords are zero terminated strings.
*/
passwd= get_null_terminated_string(&end, &bytes_remaining_in_packet,
&passwd_len);
}
Cast *passwd to an unsigned char, so that it doesn't extend the sign for if (passwd == NULL)
*passwd > 127 and become 2**32-127+ after casting to uint.
*/
uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
(uchar)(*passwd++) : strlen(passwd);
db= thd->client_capabilities & CLIENT_CONNECT_WITH_DB ?
db + passwd_len + 1 : 0;
/* strlen() can't be easily deleted without changing protocol */
uint db_len= db ? strlen(db) : 0;
if (passwd + passwd_len + db_len > (char *)net->read_pos + pkt_len)
{ {
inc_host_errors(&thd->remote.sin_addr); inc_host_errors(&thd->remote.sin_addr);
my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip); my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
return 1; return 1;
} }
size_t db_len= 0;
char *db= NULL;
if (thd->client_capabilities & CLIENT_CONNECT_WITH_DB)
{
db= get_null_terminated_string(&end, &bytes_remaining_in_packet,
&db_len);
if (db == NULL)
{
inc_host_errors(&thd->remote.sin_addr);
my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
return 1;
}
}
char db_buff[NAME_LEN + 1]; // buffer to store db in utf8
char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8
uint dummy_errors;
/* Since 4.1 all database names are stored in utf8 */ /* Since 4.1 all database names are stored in utf8 */
if (db) if (db)
{ {
......
/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. /* Copyright 2000-2011, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
...@@ -11,7 +11,8 @@ ...@@ -11,7 +11,8 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA */
/* drop and alter of tables */ /* drop and alter of tables */
...@@ -3184,11 +3185,20 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -3184,11 +3185,20 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
{ {
column->length*= sql_field->charset->mbmaxlen; column->length*= sql_field->charset->mbmaxlen;
if (key->type == Key::SPATIAL && column->length) if (key->type == Key::SPATIAL)
{ {
my_error(ER_WRONG_SUB_KEY, MYF(0)); if (column->length)
DBUG_RETURN(TRUE); {
} my_error(ER_WRONG_SUB_KEY, MYF(0));
DBUG_RETURN(TRUE);
}
if (!f_is_geom(sql_field->pack_flag))
{
my_error(ER_WRONG_ARGUMENTS, MYF(0), "SPATIAL INDEX");
DBUG_RETURN(TRUE);
}
}
if (f_is_blob(sql_field->pack_flag) || if (f_is_blob(sql_field->pack_flag) ||
(f_is_geom(sql_field->pack_flag) && key->type != Key::SPATIAL)) (f_is_geom(sql_field->pack_flag) && key->type != Key::SPATIAL))
......
...@@ -1113,7 +1113,7 @@ int ha_archive::unpack_row(azio_stream *file_to_read, uchar *record) ...@@ -1113,7 +1113,7 @@ int ha_archive::unpack_row(azio_stream *file_to_read, uchar *record)
ptr+= table->s->null_bytes; ptr+= table->s->null_bytes;
for (Field **field=table->field ; *field ; field++) for (Field **field=table->field ; *field ; field++)
{ {
if (!((*field)->is_null())) if (!((*field)->is_null_in_record(record)))
{ {
ptr= (*field)->unpack(record + (*field)->offset(table->record[0]), ptr); ptr= (*field)->unpack(record + (*field)->offset(table->record[0]), ptr);
} }
......
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