merge mysql-5.1-bugteam into mysql-5.1-security

This commit is contained in:
Georgi Kodinov 2010-08-02 10:50:15 +03:00
commit 4f738e9b7c
69 changed files with 1267 additions and 698 deletions

View file

@ -2740,6 +2740,7 @@ public:
class Cached_item_str :public Cached_item
{
Item *item;
uint32 value_max_length;
String value,tmp_value;
public:
Cached_item_str(THD *thd, Item *arg);

View file

@ -58,7 +58,9 @@ Cached_item::~Cached_item() {}
*/
Cached_item_str::Cached_item_str(THD *thd, Item *arg)
:item(arg), value(min(arg->max_length, thd->variables.max_sort_length))
:item(arg),
value_max_length(min(arg->max_length, thd->variables.max_sort_length)),
value(value_max_length)
{}
bool Cached_item_str::cmp(void)
@ -67,7 +69,7 @@ bool Cached_item_str::cmp(void)
bool tmp;
if ((res=item->val_str(&tmp_value)))
res->length(min(res->length(), value.alloced_length()));
res->length(min(res->length(), value_max_length));
if (null_value != item->null_value)
{
if ((null_value= item->null_value))

View file

@ -1024,7 +1024,7 @@ bool mysql_opt_change_db(THD *thd,
bool force_switch,
bool *cur_db_changed);
void mysql_parse(THD *thd, const char *inBuf, uint length,
void mysql_parse(THD *thd, char *rawbuf, uint length,
const char ** semicolon);
bool mysql_test_parse_for_slave(THD *thd,char *inBuf,uint length);

View file

@ -534,7 +534,11 @@ void Protocol::end_partial_result_set(THD *thd_arg)
bool Protocol::flush()
{
#ifndef EMBEDDED_LIBRARY
return net_flush(&thd->net);
bool error;
thd->main_da.can_overwrite_status= TRUE;
error= net_flush(&thd->net);
thd->main_da.can_overwrite_status= FALSE;
return error;
#else
return 0;
#endif
@ -574,7 +578,8 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
if (flags & SEND_NUM_ROWS)
{ // Packet with number of elements
uchar *pos= net_store_length(buff, list->elements);
(void) my_net_write(&thd->net, buff, (size_t) (pos-buff));
if (my_net_write(&thd->net, buff, (size_t) (pos-buff)))
DBUG_RETURN(1);
}
#ifndef DBUG_OFF
@ -698,7 +703,7 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
if (flags & SEND_DEFAULTS)
item->send(&prot, &tmp); // Send default value
if (prot.write())
break; /* purecov: inspected */
DBUG_RETURN(1);
#ifndef DBUG_OFF
field_types[count++]= field.type;
#endif
@ -711,7 +716,9 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
to show that there is no cursor.
Send no warning information, as it will be sent at statement end.
*/
write_eof_packet(thd, &thd->net, thd->server_status, thd->total_warn_count);
if (write_eof_packet(thd, &thd->net, thd->server_status,
thd->total_warn_count))
DBUG_RETURN(1);
}
DBUG_RETURN(prepare_for_send(list));

View file

@ -1653,7 +1653,8 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
thd->limit_found_rows = query->found_rows();
thd->status_var.last_query_cost= 0.0;
thd->main_da.disable_status();
if (!thd->main_da.is_set())
thd->main_da.disable_status();
BLOCK_UNLOCK_RD(query_block);
DBUG_RETURN(1); // Result sent to client

View file

@ -3391,9 +3391,13 @@ bool xid_cache_insert(XID *xid, enum xa_states xa_state)
bool xid_cache_insert(XID_STATE *xid_state)
{
pthread_mutex_lock(&LOCK_xid_cache);
DBUG_ASSERT(hash_search(&xid_cache, xid_state->xid.key(),
xid_state->xid.key_length())==0);
my_bool res=my_hash_insert(&xid_cache, (uchar*)xid_state);
if (hash_search(&xid_cache, xid_state->xid.key(), xid_state->xid.key_length()))
{
pthread_mutex_unlock(&LOCK_xid_cache);
my_error(ER_XAER_DUPID, MYF(0));
return TRUE;
}
my_bool res= my_hash_insert(&xid_cache, (uchar*)xid_state);
pthread_mutex_unlock(&LOCK_xid_cache);
return res;
}

View file

@ -658,7 +658,12 @@ void Materialized_cursor::fetch(ulong num_rows)
if ((res= table->file->rnd_next(table->record[0])))
break;
/* Send data only if the read was successful. */
result->send_data(item_list);
/*
If network write failed (i.e. due to a closed socked),
the error has already been set. Just return.
*/
if (result->send_data(item_list))
return;
}
switch (res) {

View file

@ -111,7 +111,7 @@ st_parsing_options::reset()
}
bool Lex_input_stream::init(THD *thd, const char *buff, unsigned int length)
bool Lex_input_stream::init(THD *thd, char *buff, unsigned int length)
{
DBUG_EXECUTE_IF("bug42064_simulate_oom",
DBUG_SET("+d,simulate_out_of_memory"););
@ -1292,11 +1292,10 @@ int MYSQLlex(void *arg, void *yythd)
ulong version;
version=strtol(version_str, NULL, 10);
/* Accept 'M' 'm' 'm' 'd' 'd' */
lip->yySkipn(5);
if (version <= MYSQL_VERSION_ID)
{
/* Accept 'M' 'm' 'm' 'd' 'd' */
lip->yySkipn(5);
/* Expand the content of the special comment as real code */
lip->set_echo(TRUE);
state=MY_LEX_START;
@ -1304,7 +1303,16 @@ int MYSQLlex(void *arg, void *yythd)
}
else
{
/*
Patch and skip the conditional comment to avoid it
being propagated infinitely (eg. to a slave).
*/
char *pcom= lip->yyUnput(' ');
comment_closed= ! consume_comment(lip, 1);
if (! comment_closed)
{
*pcom= '!';
}
/* version allowed to have one level of comment inside. */
}
}

View file

@ -1180,7 +1180,7 @@ public:
@retval FALSE OK
@retval TRUE Error
*/
bool init(THD *thd, const char *buff, unsigned int length);
bool init(THD *thd, char *buff, unsigned int length);
/**
Set the echo mode.
@ -1294,6 +1294,20 @@ public:
m_ptr += n;
}
/**
Puts a character back into the stream, canceling
the effect of the last yyGet() or yySkip().
Note that the echo mode should not change between calls
to unput, get, or skip from the stream.
*/
char *yyUnput(char ch)
{
*--m_ptr= ch;
if (m_echo)
m_cpp_ptr--;
return m_ptr;
}
/**
End of file indicator for the query text to parse.
@return true if there are no more characters to parse
@ -1440,7 +1454,7 @@ public:
private:
/** Pointer to the current position in the raw input stream. */
const char *m_ptr;
char *m_ptr;
/** Starting position of the last token parsed, in the raw buffer. */
const char *m_tok_start;
@ -1972,7 +1986,7 @@ public:
@retval FALSE OK
@retval TRUE Error
*/
bool init(THD *thd, const char *buff, unsigned int length)
bool init(THD *thd, char *buff, unsigned int length)
{
return m_lip.init(thd, buff, length);
}

View file

@ -4735,7 +4735,7 @@ create_sp_error:
my_error(ER_XAER_NOTA, MYF(0));
break;
}
thd->transaction.xid_state.xa_state=XA_ACTIVE;
thd->transaction.xid_state.xa_state= XA_ACTIVE;
my_ok(thd);
break;
}
@ -4755,16 +4755,16 @@ create_sp_error:
my_error(ER_XAER_OUTSIDE, MYF(0));
break;
}
if (xid_cache_search(thd->lex->xid))
{
my_error(ER_XAER_DUPID, MYF(0));
break;
}
DBUG_ASSERT(thd->transaction.xid_state.xid.is_null());
thd->transaction.xid_state.xa_state=XA_ACTIVE;
thd->transaction.xid_state.xa_state= XA_ACTIVE;
thd->transaction.xid_state.rm_error= 0;
thd->transaction.xid_state.xid.set(thd->lex->xid);
xid_cache_insert(&thd->transaction.xid_state);
if (xid_cache_insert(&thd->transaction.xid_state))
{
thd->transaction.xid_state.xa_state= XA_NOTR;
thd->transaction.xid_state.xid.null();
break;
}
thd->transaction.all.modified_non_trans_table= FALSE;
thd->options= ((thd->options & ~(OPTION_KEEP_LOG)) | OPTION_BEGIN);
thd->server_status|= SERVER_STATUS_IN_TRANS;
@ -4818,6 +4818,16 @@ create_sp_error:
case SQLCOM_XA_COMMIT:
if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
{
/*
xid_state.in_thd is always true beside of xa recovery
procedure. Note, that there is no race condition here
between xid_cache_search and xid_cache_delete, since we're always
deleting our own XID (thd->lex->xid == thd->transaction.xid_state.xid).
The only case when thd->lex->xid != thd->transaction.xid_state.xid
and xid_state->in_thd == 0 is in ha_recover() functionality,
which is called before starting client connections, and thus is
always single-threaded.
*/
XID_STATE *xs=xid_cache_search(thd->lex->xid);
if (!xs || xs->in_thd)
my_error(ER_XAER_NOTA, MYF(0));
@ -5936,13 +5946,13 @@ void mysql_init_multi_delete(LEX *lex)
Parse a query.
@param thd Current thread
@param inBuf Begining of the query text
@param rawbuf Begining of the query text
@param length Length of the query text
@param[out] found_semicolon For multi queries, position of the character of
the next query in the query text.
*/
void mysql_parse(THD *thd, const char *inBuf, uint length,
void mysql_parse(THD *thd, char *rawbuf, uint length,
const char ** found_semicolon)
{
DBUG_ENTER("mysql_parse");
@ -5968,7 +5978,7 @@ void mysql_parse(THD *thd, const char *inBuf, uint length,
lex_start(thd);
mysql_reset_thd_for_next_command(thd);
if (query_cache_send_result_to_client(thd, (char*) inBuf, length) <= 0)
if (query_cache_send_result_to_client(thd, rawbuf, length) <= 0)
{
LEX *lex= thd->lex;
@ -5977,7 +5987,7 @@ void mysql_parse(THD *thd, const char *inBuf, uint length,
Parser_state parser_state;
bool err;
if (!(err= parser_state.init(thd, inBuf, length)))
if (!(err= parser_state.init(thd, rawbuf, length)))
{
err= parse_sql(thd, & parser_state, NULL);
*found_semicolon= parser_state.m_lip.found_semicolon;
@ -6063,14 +6073,14 @@ void mysql_parse(THD *thd, const char *inBuf, uint length,
1 can be ignored
*/
bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length)
bool mysql_test_parse_for_slave(THD *thd, char *rawbuf, uint length)
{
LEX *lex= thd->lex;
bool error= 0;
DBUG_ENTER("mysql_test_parse_for_slave");
Parser_state parser_state;
if (!(error= parser_state.init(thd, inBuf, length)))
if (!(error= parser_state.init(thd, rawbuf, length)))
{
lex_start(thd);
mysql_reset_thd_for_next_command(thd);

View file

@ -3876,7 +3876,7 @@ void get_partition_set(const TABLE *table, uchar *buf, const uint index,
*/
bool mysql_unpack_partition(THD *thd,
const char *part_buf, uint part_info_len,
char *part_buf, uint part_info_len,
const char *part_state, uint part_state_len,
TABLE* table, bool is_create_table_ind,
handlerton *default_db_type,

View file

@ -78,7 +78,7 @@ void get_full_part_id_from_key(const TABLE *table, uchar *buf,
KEY *key_info,
const key_range *key_spec,
part_id_range *part_spec);
bool mysql_unpack_partition(THD *thd, const char *part_buf,
bool mysql_unpack_partition(THD *thd, char *part_buf,
uint part_info_len,
const char *part_state, uint part_state_len,
TABLE *table, bool is_create_table_ind,

View file

@ -263,8 +263,11 @@ static bool send_prep_stmt(Prepared_statement *stmt, uint columns)
&stmt->lex->param_list,
Protocol::SEND_EOF);
}
/* Flag that a response has already been sent */
thd->main_da.disable_status();
if (!error)
/* Flag that a response has already been sent */
thd->main_da.disable_status();
DBUG_RETURN(error);
}
#else
@ -790,7 +793,7 @@ static bool insert_params_with_log(Prepared_statement *stmt, uchar *null_array,
type (the types are supplied at execute). Check that the
supplied type of placeholder can accept a data stream.
*/
else if (!is_param_long_data_type(param))
else if (! is_param_long_data_type(param))
DBUG_RETURN(1);
res= param->query_val_str(&str);
if (param->convert_str_value(thd))
@ -836,7 +839,7 @@ static bool insert_params(Prepared_statement *stmt, uchar *null_array,
type (the types are supplied at execute). Check that the
supplied type of placeholder can accept a data stream.
*/
else if (is_param_long_data_type(param))
else if (! is_param_long_data_type(param))
DBUG_RETURN(1);
if (param->convert_str_value(stmt->thd))
DBUG_RETURN(1); /* out of memory */

View file

@ -356,6 +356,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos,
#ifndef DBUG_OFF
int left_events = max_binlog_dump_events;
#endif
int old_max_allowed_packet= thd->variables.max_allowed_packet;
DBUG_ENTER("mysql_binlog_send");
DBUG_PRINT("enter",("log_ident: '%s' pos: %ld", log_ident, (long) pos));
@ -761,6 +762,7 @@ end:
pthread_mutex_lock(&LOCK_thread_count);
thd->current_linfo = 0;
pthread_mutex_unlock(&LOCK_thread_count);
thd->variables.max_allowed_packet= old_max_allowed_packet;
DBUG_VOID_RETURN;
err:
@ -778,6 +780,7 @@ err:
pthread_mutex_unlock(&LOCK_thread_count);
if (file >= 0)
(void) my_close(file, MYF(MY_WME));
thd->variables.max_allowed_packet= old_max_allowed_packet;
my_message(my_errno, errmsg, MYF(0));
DBUG_VOID_RETURN;
@ -1418,6 +1421,7 @@ bool mysql_show_binlog_events(THD* thd)
bool ret = TRUE;
IO_CACHE log;
File file = -1;
int old_max_allowed_packet= thd->variables.max_allowed_packet;
DBUG_ENTER("mysql_show_binlog_events");
Log_event::init_show_field_list(&field_list);
@ -1556,6 +1560,7 @@ err:
pthread_mutex_lock(&LOCK_thread_count);
thd->current_linfo = 0;
pthread_mutex_unlock(&LOCK_thread_count);
thd->variables.max_allowed_packet= old_max_allowed_packet;
DBUG_RETURN(ret);
}

View file

@ -1,4 +1,4 @@
/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.
/* Copyright 2000, 2010 Oracle and/or its affiliates. All rights reserved.
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
@ -9,9 +9,9 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
/* Function with list databases, tables or fields */
@ -2997,7 +2997,7 @@ make_table_name_list(THD *thd, List<LEX_STRING> *table_names, LEX *lex,
*/
if (res == FIND_FILES_DIR)
{
if (lex->sql_command != SQLCOM_SELECT)
if (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND)
return 1;
thd->clear_error();
return 2;

View file

@ -441,7 +441,7 @@ typedef struct st_table_share
#ifdef WITH_PARTITION_STORAGE_ENGINE
/** @todo: Move into *ha_data for partitioning */
bool auto_partitioned;
const char *partition_info;
char *partition_info;
uint partition_info_len;
uint partition_info_buffer_size;
const char *part_state;