~ubuntu-branches/ubuntu/natty/mysql-5.1/natty-proposed

« back to all changes in this revision

Viewing changes to sql/sql_parse.cc

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2012-02-22 08:30:45 UTC
  • mfrom: (1.4.1)
  • Revision ID: package-import@ubuntu.com-20120222083045-2rd53r4bnyx7qus4
Tags: 5.1.61-0ubuntu0.11.04.1
* SECURITY UPDATE: Update to 5.1.61 to fix multiple security issues
  (LP: #937869)
  - http://www.oracle.com/technetwork/topics/security/cpujan2012-366304.html
  - CVE-2011-2262
  - CVE-2012-0075
  - CVE-2012-0112
  - CVE-2012-0113
  - CVE-2012-0114
  - CVE-2012-0115
  - CVE-2012-0116
  - CVE-2012-0117
  - CVE-2012-0118
  - CVE-2012-0119
  - CVE-2012-0120
  - CVE-2012-0484
  - CVE-2012-0485
  - CVE-2012-0486
  - CVE-2012-0487
  - CVE-2012-0488
  - CVE-2012-0489
  - CVE-2012-0490
  - CVE-2012-0491
  - CVE-2012-0492
  - CVE-2012-0493
  - CVE-2012-0494
  - CVE-2012-0495
  - CVE-2012-0496

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.
 
1
/*
 
2
   Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
2
3
 
3
4
   This program is free software; you can redistribute it and/or modify
4
5
   it under the terms of the GNU General Public License as published by
11
12
 
12
13
   You should have received a copy of the GNU General Public License
13
14
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
15
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
 
16
*/
15
17
 
16
18
#define MYSQL_LEX 1
17
19
#include "mysql_priv.h"
490
492
    query= (char *) thd->memdup_w_gap(buff, length + 1,
491
493
                                      thd->db_length + 1 +
492
494
                                      QUERY_CACHE_FLAGS_SIZE);
 
495
    size_t db_len= 0;
 
496
    memcpy(query + length + 1, (char *) &db_len, sizeof(size_t));
493
497
    thd->set_query(query, length);
494
498
    DBUG_PRINT("query",("%-.4096s", thd->query()));
495
499
#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
1153
1157
 
1154
1158
    if (ptr < packet_end)
1155
1159
    {
 
1160
      CHARSET_INFO *cs;
1156
1161
      if (ptr + 2 > packet_end)
1157
1162
      {
1158
1163
        my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
1159
1164
        break;
1160
1165
      }
1161
1166
 
1162
 
      cs_number= uint2korr(ptr);
 
1167
      if ((cs_number= uint2korr(ptr)) &&
 
1168
          (cs= get_charset(cs_number, MYF(0))) &&
 
1169
          !is_supported_parser_charset(cs))
 
1170
      {
 
1171
        /* Disallow non-supported parser character sets: UCS2, UTF16, UTF32 */
 
1172
        my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "character_set_client",
 
1173
                 cs->csname);
 
1174
        break;
 
1175
      }        
1163
1176
    }
1164
1177
 
1165
1178
    /* Convert database name to utf8 */
1205
1218
 
1206
1219
      if (cs_number)
1207
1220
      {
1208
 
        thd_init_client_charset(thd, cs_number);
 
1221
        /*
 
1222
          We have checked charset earlier,
 
1223
          so thd_init_client_charset cannot fail.
 
1224
        */
 
1225
        if (thd_init_client_charset(thd, cs_number))
 
1226
          DBUG_ASSERT(0);
1209
1227
        thd->update_charset();
1210
1228
      }
1211
1229
    }
1474
1492
#endif
1475
1493
  case COM_REFRESH:
1476
1494
  {
1477
 
    bool not_used;
 
1495
    int not_used;
 
1496
 
 
1497
    /*
 
1498
      Initialize thd->lex since it's used in many base functions, such as
 
1499
      open_tables(). Otherwise, it remains unitialized and may cause crash
 
1500
      during execution of COM_REFRESH.
 
1501
    */
 
1502
    lex_start(thd);
 
1503
    
1478
1504
    status_var_increment(thd->status_var.com_stat[SQLCOM_FLUSH]);
1479
1505
    ulong options= (ulong) (uchar) packet[0];
1480
1506
    if (check_global_access(thd,RELOAD_ACL))
1888
1914
    pos--;
1889
1915
    packet_length--;
1890
1916
  }
1891
 
  /* We must allocate some extra memory for query cache */
 
1917
  /* We must allocate some extra memory for query cache 
 
1918
 
 
1919
    The query buffer layout is:
 
1920
       buffer :==
 
1921
            <statement>   The input statement(s)
 
1922
            '\0'          Terminating null char  (1 byte)
 
1923
            <length>      Length of following current database name (size_t)
 
1924
            <db_name>     Name of current database
 
1925
            <flags>       Flags struct
 
1926
  */
1892
1927
  if (! (query= (char*) thd->memdup_w_gap(packet,
1893
1928
                                          packet_length,
1894
 
                                          1 + thd->db_length +
 
1929
                                          1 + sizeof(size_t) + thd->db_length +
1895
1930
                                          QUERY_CACHE_FLAGS_SIZE)))
1896
1931
      return TRUE;
1897
1932
  query[packet_length]= '\0';
 
1933
  /*
 
1934
    Space to hold the name of the current database is allocated.  We
 
1935
    also store this length, in case current database is changed during
 
1936
    execution.  We might need to reallocate the 'query' buffer
 
1937
  */
 
1938
  char *len_pos = (query + packet_length + 1);
 
1939
  memcpy(len_pos, (char *) &thd->db_length, sizeof(size_t));
 
1940
    
1898
1941
  thd->set_query(query, packet_length);
1899
1942
 
1900
1943
  /* Reclaim some memory */
2601
2644
      goto end_with_restore_list;
2602
2645
#endif
2603
2646
    /*
 
2647
      If no engine type was given, work out the default now
 
2648
      rather than at parse-time.
 
2649
    */
 
2650
    if (!(create_info.used_fields & HA_CREATE_USED_ENGINE))
 
2651
      create_info.db_type= ha_default_handlerton(thd);
 
2652
    /*
2604
2653
      If we are using SET CHARSET without DEFAULT, add an implicit
2605
2654
      DEFAULT to not confuse old users. (This may change).
2606
2655
    */
3227
3276
      {
3228
3277
        Incident_log_event ev(thd, incident);
3229
3278
        (void) mysql_bin_log.write(&ev);        /* error is ignored */
3230
 
        mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE);
 
3279
        if (mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE))
 
3280
        {
 
3281
          res= 1;
 
3282
          break;
 
3283
        }
3231
3284
      }
3232
3285
      DBUG_PRINT("debug", ("Just after generate_incident()"));
3233
3286
    }
3963
4016
            hostname_requires_resolving(user->host.str))
3964
4017
          push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
3965
4018
                              ER_WARN_HOSTNAME_WONT_WORK,
3966
 
                              ER(ER_WARN_HOSTNAME_WONT_WORK),
3967
 
                              user->host.str);
 
4019
                              ER(ER_WARN_HOSTNAME_WONT_WORK));
3968
4020
        // Are we trying to change a password of another user
3969
4021
        DBUG_ASSERT(user->host.str != 0);
3970
4022
        if (strcmp(thd->security_ctx->user, user->user.str) ||
4051
4103
    lex->no_write_to_binlog= 1;
4052
4104
  case SQLCOM_FLUSH:
4053
4105
  {
4054
 
    bool write_to_binlog;
 
4106
    int write_to_binlog;
4055
4107
    if (check_global_access(thd,RELOAD_ACL))
4056
4108
      goto error;
4057
4109
 
4068
4120
      /*
4069
4121
        Presumably, RESET and binlog writing doesn't require synchronization
4070
4122
      */
4071
 
      if (!lex->no_write_to_binlog && write_to_binlog)
 
4123
 
 
4124
      if (write_to_binlog > 0)  // we should write
 
4125
      { 
 
4126
        if (!lex->no_write_to_binlog)
 
4127
          res= write_bin_log(thd, FALSE, thd->query(), thd->query_length());
 
4128
      } else if (write_to_binlog < 0) 
4072
4129
      {
4073
 
        if ((res= write_bin_log(thd, FALSE, thd->query(), thd->query_length())))
4074
 
          break;
4075
 
      }
4076
 
      my_ok(thd);
 
4130
        /* 
 
4131
           We should not write, but rather report error because 
 
4132
           reload_acl_and_cache binlog interactions failed 
 
4133
         */
 
4134
        res= 1;
 
4135
      } 
 
4136
 
 
4137
      if (!res)
 
4138
        my_ok(thd);
4077
4139
    } 
4078
4140
    
4079
4141
    break;
5861
5923
  lex->nest_level++;
5862
5924
  if (lex->nest_level > (int) MAX_SELECT_NESTING)
5863
5925
  {
5864
 
    my_error(ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT,MYF(0),MAX_SELECT_NESTING);
 
5926
    my_error(ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT, MYF(0));
5865
5927
    DBUG_RETURN(1);
5866
5928
  }
5867
5929
  select_lex->nest_level= lex->nest_level;
5868
 
  /*
5869
 
    Don't evaluate this subquery during statement prepare even if
5870
 
    it's a constant one. The flag is switched off in the end of
5871
 
    mysqld_stmt_prepare.
5872
 
  */
5873
 
  if (thd->stmt_arena->is_stmt_prepare())
5874
 
    select_lex->uncacheable|= UNCACHEABLE_PREPARE;
5875
5930
  if (move_down)
5876
5931
  {
5877
5932
    SELECT_LEX_UNIT *unit;
6862
6917
  @param thd Thread handler (can be NULL!)
6863
6918
  @param options What should be reset/reloaded (tables, privileges, slave...)
6864
6919
  @param tables Tables to flush (if any)
6865
 
  @param write_to_binlog True if we can write to the binlog.
 
6920
  @param write_to_binlog < 0 if there was an error while interacting with the binary log inside
 
6921
                         reload_acl_and_cache, 
 
6922
                         0 if we should not write to the binary log, 
 
6923
                         > 0 if we can write to the binlog.
6866
6924
               
6867
6925
  @note Depending on 'options', it may be very bad to write the
6868
6926
    query to the binlog (e.g. FLUSH SLAVE); this is a
6876
6934
*/
6877
6935
 
6878
6936
bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
6879
 
                          bool *write_to_binlog)
 
6937
                          int *write_to_binlog)
6880
6938
{
6881
6939
  bool result=0;
6882
6940
  select_errors=0;                              /* Write if more errors */
6883
 
  bool tmp_write_to_binlog= 1;
 
6941
  int tmp_write_to_binlog= *write_to_binlog= 1;
6884
6942
 
6885
6943
  DBUG_ASSERT(!thd || !thd->in_sub_stmt);
6886
6944
 
6912
6970
          When an error is returned, my_message may have not been called and
6913
6971
          the client will hang waiting for a response.
6914
6972
        */
6915
 
        my_error(ER_UNKNOWN_ERROR, MYF(0), "FLUSH PRIVILEGES failed");
 
6973
        my_error(ER_UNKNOWN_ERROR, MYF(0));
6916
6974
      }
6917
6975
    }
6918
6976
 
6943
7001
    tmp_write_to_binlog= 0;
6944
7002
    if( mysql_bin_log.is_open() )
6945
7003
    {
6946
 
      mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE);
 
7004
      if (mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE))
 
7005
        *write_to_binlog= -1;
6947
7006
    }
6948
7007
#ifdef HAVE_REPLICATION
 
7008
    int rotate_error= 0;
6949
7009
    pthread_mutex_lock(&LOCK_active_mi);
6950
 
    rotate_relay_log(active_mi);
 
7010
    rotate_error= rotate_relay_log(active_mi);
6951
7011
    pthread_mutex_unlock(&LOCK_active_mi);
 
7012
    if (rotate_error)
 
7013
      *write_to_binlog= -1;
6952
7014
#endif
6953
7015
 
6954
7016
    /* flush slow and general logs */
6957
7019
    if (ha_flush_logs(NULL))
6958
7020
      result=1;
6959
7021
    if (flush_error_log())
6960
 
      result=1;
 
7022
    {
 
7023
      /*
 
7024
        When flush_error_log() failed, my_error() has not been called.
 
7025
        So, we have to do it here to keep the protocol.
 
7026
      */
 
7027
      my_error(ER_UNKNOWN_ERROR, MYF(0));
 
7028
      result= 1;
 
7029
    }
6961
7030
  }
6962
7031
#ifdef HAVE_QUERY_CACHE
6963
7032
  if (options & REFRESH_QUERY_CACHE_FREE)
7006
7075
        return 1;                               // Killed
7007
7076
      if (close_cached_tables(thd, tables, FALSE, (options & REFRESH_FAST) ?
7008
7077
                              FALSE : TRUE, TRUE))
7009
 
          result= 1;
 
7078
      {
 
7079
        /*
 
7080
          NOTE: my_error() has been already called by reopen_tables() within
 
7081
          close_cached_tables().
 
7082
        */
 
7083
        result= 1;
 
7084
      }
7010
7085
      
7011
7086
      if (make_global_read_lock_block_commit(thd)) // Killed
7012
7087
      {
7019
7094
    {
7020
7095
      if (close_cached_tables(thd, tables, FALSE, (options & REFRESH_FAST) ?
7021
7096
                              FALSE : TRUE, FALSE))
 
7097
      {
 
7098
        /*
 
7099
          NOTE: my_error() has been already called by reopen_tables() within
 
7100
          close_cached_tables().
 
7101
        */
7022
7102
        result= 1;
 
7103
      }
7023
7104
    }
7024
7105
    my_dbopt_cleanup();
7025
7106
  }
7036
7117
    tmp_write_to_binlog= 0;
7037
7118
    if (reset_master(thd))
7038
7119
    {
7039
 
      result=1;
 
7120
      /* NOTE: my_error() has been already called by reset_master(). */
 
7121
      result= 1;
7040
7122
    }
7041
7123
  }
7042
7124
#endif
7044
7126
   if (options & REFRESH_DES_KEY_FILE)
7045
7127
   {
7046
7128
     if (des_key_file && load_des_key_file(des_key_file))
7047
 
         result= 1;
 
7129
     {
 
7130
       /* NOTE: my_error() has been already called by load_des_key_file(). */
 
7131
       result= 1;
 
7132
     }
7048
7133
   }
7049
7134
#endif
7050
7135
#ifdef HAVE_REPLICATION
7053
7138
   tmp_write_to_binlog= 0;
7054
7139
   pthread_mutex_lock(&LOCK_active_mi);
7055
7140
   if (reset_slave(thd, active_mi))
7056
 
     result=1;
 
7141
   {
 
7142
     /* NOTE: my_error() has been already called by reset_slave(). */
 
7143
     result= 1;
 
7144
   }
7057
7145
   pthread_mutex_unlock(&LOCK_active_mi);
7058
7146
 }
7059
7147
#endif
7060
7148
 if (options & REFRESH_USER_RESOURCES)
7061
7149
   reset_mqh((LEX_USER *) NULL, 0);             /* purecov: inspected */
7062
 
 *write_to_binlog= tmp_write_to_binlog;
 
7150
 if (*write_to_binlog != -1)
 
7151
   *write_to_binlog= tmp_write_to_binlog;
7063
7152
 /*
7064
7153
   If the query was killed then this function must fail.
7065
7154
 */
7944
8033
 
7945
8034
  bool mysql_parse_status= MYSQLparse(thd) != 0;
7946
8035
 
7947
 
  /* Check that if MYSQLparse() failed, thd->is_error() is set. */
 
8036
  /*
 
8037
    Check that if MYSQLparse() failed, thd->is_error() is set (unless
 
8038
    we have an error handler installed, which might have silenced error).
 
8039
  */
7948
8040
 
7949
8041
  DBUG_ASSERT(!mysql_parse_status ||
7950
 
              (mysql_parse_status && thd->is_error()));
 
8042
              (mysql_parse_status && thd->is_error()) ||
 
8043
              (mysql_parse_status && thd->get_internal_handler()));
7951
8044
 
7952
8045
  /* Reset parser state. */
7953
8046