diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/des_key_file.cc | 45 | ||||
-rw-r--r-- | sql/item_create.cc | 3 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 150 | ||||
-rw-r--r-- | sql/item_strfunc.h | 13 | ||||
-rw-r--r-- | sql/item_timefunc.cc | 2 | ||||
-rw-r--r-- | sql/lex.h | 1 | ||||
-rw-r--r-- | sql/mysql_priv.h | 6 | ||||
-rw-r--r-- | sql/mysqld.cc | 2 | ||||
-rw-r--r-- | sql/sql_parse.cc | 28 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 58 |
10 files changed, 202 insertions, 106 deletions
diff --git a/sql/des_key_file.cc b/sql/des_key_file.cc index c6ac9ab6059..d9c924b5a3c 100644 --- a/sql/des_key_file.cc +++ b/sql/des_key_file.cc @@ -19,25 +19,37 @@ #ifdef HAVE_OPENSSL +struct st_des_keyschedule des_keyschedule[10]; +uint des_default_key; +pthread_mutex_t LOCK_des_key_file; +static int initialized; + /* Function which loads DES keys from plaintext file into memory on MySQL - server startup and on command FLUSH DES_KEYS. Blame tonu@spam.ee on bugs ;) -*/ + server startup and on command FLUSH DES_KEY_FILE. + Blame tonu@spam.ee on bugs ;) -struct st_des_keyschedule des_keyschedule[10]; -uint des_default_key; + RETURN + 0 ok + 1 Error +*/ -void +bool load_des_key_file(const char *file_name) { + bool result=1; File file; - des_cblock ivec={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - char offset; IO_CACHE io; DBUG_ENTER("load_des_key_file"); DBUG_PRINT("enter",("name: %s",file_name)); - VOID(pthread_mutex_lock(&LOCK_open)); + if (!initialized) + { + initialized=1; + pthread_mutex_init(&LOCK_des_key_file,MY_MUTEX_INIT_FAST); + } + + VOID(pthread_mutex_lock(&LOCK_des_key_file)); if ((file=my_open(file_name,O_RDONLY | O_BINARY ,MYF(MY_WME))) < 0 || init_io_cache(&io, file, IO_SIZE*2, READ_CACHE, 0, 0, MYF(MY_WME))) goto error; @@ -47,7 +59,7 @@ load_des_key_file(const char *file_name) for (;;) { char *start, *end; - char buf[1024]; + char buf[1024], offset; st_des_keyblock keyblock; uint length; @@ -60,10 +72,12 @@ load_des_key_file(const char *file_name) // Remove newline and possible other control characters for (start=buf+1 ; isspace(*start) ; start++) ; end=buf+length; - for (end=strend(buf) ; end > start && iscntrl(end[-1]) ; end--) ; + for (end=strend(buf) ; end > start && !isgraph(end[-1]) ; end--) ; if (start != end) { + des_cblock ivec; + bzero((char*) &ivec,sizeof(ivec)); // We make good 24-byte (168 bit) key from given plaintext key with MD5 EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL, (uchar *) start, (int) (end-start),1, @@ -76,11 +90,10 @@ load_des_key_file(const char *file_name) des_default_key= (uint) offset; // use first as def. } } - else - { - DBUG_PRINT("des",("wrong offset: %c",offset)); - } + else if (offset != '#') + sql_print_error("load_des_file: Found wrong key_number: %c",offset); } + result=0; error: if (file >= 0) @@ -88,7 +101,7 @@ error: my_close(file,MYF(0)); end_io_cache(&io); } - VOID(pthread_mutex_unlock(&LOCK_open)); - DBUG_VOID_RETURN; + VOID(pthread_mutex_unlock(&LOCK_des_key_file)); + DBUG_RETURN(result); } #endif /* HAVE_OPENSSL */ diff --git a/sql/item_create.cc b/sql/item_create.cc index 71dc99f2558..a9567414b0b 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -151,8 +151,7 @@ Item *create_func_get_lock(Item* a, Item *b) Item *create_func_hex(Item *a) { - return new Item_func_conv(a,new Item_int((int32) 10,2), - new Item_int((int32) 16,2)); + return new Item_func_hex(a); } Item *create_func_inet_ntoa(Item* a) diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 792c76ebc0d..c64fdc7a049 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -209,78 +209,84 @@ void Item_func_concat::fix_length_and_dec() Function des_encrypt() by tonu@spam.ee & monty Works only if compiled with OpenSSL library support. This returns a binary string where first character is - CHAR(128 | tail-length << 4 | key-number). - If one uses a string key key_number is 0. + CHAR(128 | key-number). + If one uses a string key key_number is 127. Encryption result is longer than original by formula: - new_length= (8-(original_length % 8))+1 + new_length= org_length + (8-(org_length % 8))+1 */ String *Item_func_des_encrypt::val_str(String *str) { #ifdef HAVE_OPENSSL - des_cblock ivec={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + des_cblock ivec; struct st_des_keyblock keyblock; struct st_des_keyschedule keyschedule; - struct st_des_keyschedule *keyschedule_ptr; const char *append_str="********"; uint key_number, res_length, tail; String *res= args[0]->val_str(str); if ((null_value=args[0]->null_value)) return 0; - if (res->length() == 0) + if ((res_length=res->length()) == 0) return &empty_string; if (arg_count == 1) - keyschedule_ptr= &des_keyschedule[key_number=des_default_key]; + { + /* Protect against someone doing FLUSH DES_KEY_FILE */ + VOID(pthread_mutex_lock(&LOCK_des_key_file)); + keyschedule= des_keyschedule[key_number=des_default_key]; + VOID(pthread_mutex_unlock(&LOCK_des_key_file)); + } else if (args[1]->result_type() == INT_RESULT) { key_number= (uint) args[1]->val_int(); if (key_number > 9) goto error; - keyschedule_ptr= &des_keyschedule[key_number]; + VOID(pthread_mutex_lock(&LOCK_des_key_file)); + keyschedule= des_keyschedule[key_number]; + VOID(pthread_mutex_unlock(&LOCK_des_key_file)); } else { - uint tail,res_length; String *keystr=args[1]->val_str(&tmp_value); if (!keystr) goto error; - key_number=15; // User key string + key_number=127; // User key string /* We make good 24-byte (168 bit) key from given plaintext key with MD5 */ - keyschedule_ptr= &keyschedule; + bzero((char*) &ivec,sizeof(ivec)); EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL, (uchar*) keystr->ptr(), (int) keystr->length(), 1, (uchar*) &keyblock,ivec); - des_set_key_unchecked(&keyblock.key1,keyschedule_ptr->ks1); - des_set_key_unchecked(&keyblock.key2,keyschedule_ptr->ks2); - des_set_key_unchecked(&keyblock.key3,keyschedule_ptr->ks3); + des_set_key_unchecked(&keyblock.key1,keyschedule.ks1); + des_set_key_unchecked(&keyblock.key2,keyschedule.ks2); + des_set_key_unchecked(&keyblock.key3,keyschedule.ks3); } /* The problem: DES algorithm requires original data to be in 8-bytes - chunks. Missing bytes get filled with zeros and result of encryption - can be up to 7 bytes longer than original string. When decrypted, + chunks. Missing bytes get filled with '*'s and result of encryption + can be up to 8 bytes longer than original string. When decrypted, we do not know the size of original string :( - We add one byte with value 0x1..0x8 as the second byte to original - plaintext marking change of string length. + We add one byte with value 0x1..0x8 as the last byte of the padded + string marking change of string length. */ - tail= (7-(res->length()+7) % 8); // 0..7 marking extra length - res_length=res->length()+tail+1; - if (tail && res->append(append_str, tail) || tmp_value.alloc(res_length)) + tail= (8-(res_length) % 8); // 1..8 marking extra length + res_length+=tail; + if (tail && res->append(append_str, tail) || tmp_value.alloc(res_length+1)) goto error; - - tmp_value.length(res_length); - tmp_value[0]=(char) (128 | tail << 4 | key_number); + (*res)[res_length-1]=tail; // save extra length + tmp_value.length(res_length+1); + tmp_value[0]=(char) (128 | key_number); // Real encryption + bzero((char*) &ivec,sizeof(ivec)); des_ede3_cbc_encrypt((const uchar*) (res->ptr()), (uchar*) (tmp_value.ptr()+1), - res->length(), - keyschedule_ptr->ks1, - keyschedule_ptr->ks2, - keyschedule_ptr->ks3, + res_length, + keyschedule.ks1, + keyschedule.ks2, + keyschedule.ks3, &ivec, TRUE); return &tmp_value; @@ -295,24 +301,27 @@ String *Item_func_des_decrypt::val_str(String *str) { #ifdef HAVE_OPENSSL des_key_schedule ks1, ks2, ks3; - des_cblock ivec={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + des_cblock ivec; struct st_des_keyblock keyblock; struct st_des_keyschedule keyschedule; - struct st_des_keyschedule *keyschedule_ptr; String *res= args[0]->val_str(str); + uint length=res->length(),tail; if ((null_value=args[0]->null_value)) return 0; - if (res->length() < 9 || (res->length() % 8) != 1 || !((*res)[0] & 128)) + length=res->length(); + if (length < 9 || (length % 8) != 1 || !((*res)[0] & 128)) return res; // Skip decryption if not encrypted if (arg_count == 1) // If automatic uncompression { - uint key_number=(uint) (*res)[0] & 15; + uint key_number=(uint) (*res)[0] & 127; // Check if automatic key and that we have privilege to uncompress using it if (!(current_thd->master_access & PROCESS_ACL) || key_number > 9) goto error; - keyschedule_ptr= &des_keyschedule[key_number]; + VOID(pthread_mutex_lock(&LOCK_des_key_file)); + keyschedule= des_keyschedule[key_number]; + VOID(pthread_mutex_unlock(&LOCK_des_key_file)); } else { @@ -321,26 +330,30 @@ String *Item_func_des_decrypt::val_str(String *str) if (!keystr) goto error; - keyschedule_ptr= &keyschedule; + bzero((char*) &ivec,sizeof(ivec)); EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL, (uchar*) keystr->ptr(),(int) keystr->length(), 1,(uchar*) &keyblock,ivec); // Here we set all 64-bit keys (56 effective) one by one - des_set_key_unchecked(&keyblock.key1,keyschedule_ptr->ks1); - des_set_key_unchecked(&keyblock.key2,keyschedule_ptr->ks2); - des_set_key_unchecked(&keyblock.key3,keyschedule_ptr->ks3); + des_set_key_unchecked(&keyblock.key1,keyschedule.ks1); + des_set_key_unchecked(&keyblock.key2,keyschedule.ks2); + des_set_key_unchecked(&keyblock.key3,keyschedule.ks3); } - if (tmp_value.alloc(res->length()-1)) + if (tmp_value.alloc(length-1)) goto error; - /* Restore old length of key */ - tmp_value.length(res->length()-1-(((uchar) (*res)[0] >> 4) & 7)); + + bzero((char*) &ivec,sizeof(ivec)); des_ede3_cbc_encrypt((const uchar*) res->ptr()+1, (uchar*) (tmp_value.ptr()), - res->length()-1, - keyschedule_ptr->ks1, - keyschedule_ptr->ks2, - keyschedule_ptr->ks3, + length-1, + keyschedule.ks1, + keyschedule.ks2, + keyschedule.ks3, &ivec, FALSE); + /* Restore old length of key */ + if ((tail=(uint) (uchar) tmp_value[length-2]) > 8) + goto error; // Wrong key + tmp_value.length(length-1-tail); return &tmp_value; error: @@ -1274,9 +1287,9 @@ String *Item_func_soundex::val_str(String *str) if ((null_value=args[0]->null_value)) return 0; /* purecov: inspected */ - if (str_value.alloc(max(res->length(),4))) + if (tmp_value.alloc(max(res->length(),4))) return str; /* purecov: inspected */ - char *to= (char *) str_value.ptr(); + char *to= (char *) tmp_value.ptr(); char *from= (char *) res->ptr(), *end=from+res->length(); while (from != end && isspace(*from)) // Skip pre-space @@ -1300,11 +1313,11 @@ String *Item_func_soundex::val_str(String *str) last_ch = ch; // save code of last input letter } // for next double-letter check } - for (end=(char*) str_value.ptr()+4 ; to < end ; to++) + for (end=(char*) tmp_value.ptr()+4 ; to < end ; to++) *to = '0'; *to=0; // end string - str_value.length((uint) (to-str_value.ptr())); - return &str_value; + tmp_value.length((uint) (to-tmp_value.ptr())); + return &tmp_value; } @@ -1759,6 +1772,45 @@ String *Item_func_conv::val_str(String *str) return str; } + +String *Item_func_hex::val_str(String *str) +{ + if (args[0]->result_type() != STRING_RESULT) + { + /* Return hex of unsigned longlong value */ + longlong dec= args[0]->val_int(); + char ans[65],*ptr; + if ((null_value= args[0]->null_value)) + return 0; + ptr= longlong2str(dec,ans,16); + if (str->copy(ans,(uint32) (ptr-ans))) + return &empty_string; // End of memory + return str; + } + + /* Convert given string to a hex string, character by character */ + String *res= args[0]->val_str(str); + const char *from, *end; + char *to; + if (!res || tmp_value.alloc(res->length()*2)) + { + null_value=1; + return 0; + } + null_value=0; + tmp_value.length(res->length()*2); + for (from=res->ptr(), end=from+res->length(), to= (char*) tmp_value.ptr(); + from != end ; + from++, to+=2) + { + uint tmp=(uint) (uchar) *from; + to[0]=_dig_vec[tmp >> 4]; + to[1]=_dig_vec[tmp & 15]; + } + return &tmp_value; +} + + #include <my_dir.h> // For my_stat String *Item_load_file::val_str(String *str) diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index ba2d6ffc3f0..e92dcf806db 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -297,6 +297,7 @@ public: class Item_func_soundex :public Item_str_func { + String tmp_value; public: Item_func_soundex(Item *a) :Item_str_func(a) {} String *val_str(String *); @@ -412,6 +413,18 @@ public: void fix_length_and_dec() { decimals=0; max_length=64; } }; + +class Item_func_hex :public Item_str_func +{ + String tmp_value; +public: + Item_func_hex(Item *a) :Item_str_func(a) {} + const char *func_name() const { return "hex"; } + String *val_str(String *); + void fix_length_and_dec() { decimals=0; max_length=args[0]->max_length*2; } +}; + + class Item_func_binary :public Item_str_func { public: diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index e65f7679cae..2b1bb9cae0e 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -672,7 +672,7 @@ String *Item_func_date_format::val_str(String *str) else size=format_length(format); if (format == str) - str=&str_value; // Save result here + str= &str_value; // Save result here if (str->alloc(size)) { null_value=1; diff --git a/sql/lex.h b/sql/lex.h index d20141a560e..d72d2ff63a4 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -111,6 +111,7 @@ static SYMBOL symbols[] = { { "DAY_SECOND", SYM(DAY_SECOND_SYM),0,0}, { "DEC", SYM(DECIMAL_SYM),0,0}, { "DECIMAL", SYM(DECIMAL_SYM),0,0}, + { "DES_KEY_FILE", SYM(DES_KEY_FILE),0,0}, { "DEFAULT", SYM(DEFAULT),0,0}, { "DELAYED", SYM(DELAYED_SYM),0,0}, { "DELAY_KEY_WRITE", SYM(DELAY_KEY_WRITE_SYM),0,0}, diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index a6859e31bde..fece60dd49c 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -263,7 +263,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list); bool mysql_change_db(THD *thd,const char *name); void mysql_parse(THD *thd,char *inBuf,uint length); void mysql_init_select(LEX *lex); -void mysql_new_select(LEX *lex); +bool mysql_new_select(LEX *lex); void init_max_user_conn(void); void free_max_user_conn(void); pthread_handler_decl(handle_one_connection,arg); @@ -405,9 +405,11 @@ struct st_des_keyschedule { des_key_schedule ks1, ks2, ks3; }; +extern char *des_key_file; extern struct st_des_keyschedule des_keyschedule[10]; extern uint des_default_key; -void load_des_key_file(const char *file_name); +extern pthread_mutex_t LOCK_des_key_file; +bool load_des_key_file(const char *file_name); #endif /* HAVE_OPENSSL */ /* sql_list.c */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index a8b9a799c56..786c0c2ad38 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -242,7 +242,7 @@ static char glob_hostname[FN_REFLEN]; #include "sslopt-vars.h" #ifdef HAVE_OPENSSL -static char * des_key_file = 0; +char *des_key_file = 0; struct st_VioSSLAcceptorFd * ssl_acceptor_fd = 0; #endif /* HAVE_OPENSSL */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 12646f0737f..ebe8fc979bf 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2431,9 +2431,10 @@ mysql_init_select(LEX *lex) { SELECT_LEX *select_lex = lex->select; select_lex->where=select_lex->having=0; - select_lex->select_limit=current_thd->default_select_limit; + select_lex->select_limit=lex->thd->default_select_limit; select_lex->offset_limit=0; - select_lex->options=0; select_lex->linkage=UNSPECIFIED_TYPE; + select_lex->options=0; + select_lex->linkage=UNSPECIFIED_TYPE; lex->exchange = 0; lex->proc_list.first=0; select_lex->order_list.elements=select_lex->group_list.elements=0; @@ -2444,18 +2445,25 @@ mysql_init_select(LEX *lex) select_lex->next = (SELECT_LEX *)NULL; } -void +bool mysql_new_select(LEX *lex) { SELECT_LEX *select_lex = (SELECT_LEX *) lex->thd->calloc(sizeof(SELECT_LEX)); + if (!select_lex) + return 1; lex->select->next=select_lex; lex->select=select_lex; select_lex->table_list.next= (byte**) &select_lex->table_list.first; - select_lex->item_list.empty(); select_lex->when_list.empty(); - select_lex->expr_list.empty(); select_lex->interval_list.empty(); - select_lex->use_index.empty(); select_lex->ftfunc_list.empty(); + select_lex->item_list.empty(); + select_lex->when_list.empty(); + select_lex->expr_list.empty(); + select_lex->interval_list.empty(); + select_lex->use_index.empty(); + select_lex->ftfunc_list.empty(); + return 0; } + void mysql_parse(THD *thd,char *inBuf,uint length) { @@ -3035,7 +3043,13 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables) reset_master(); if (options & REFRESH_SLAVE) reset_slave(); - +#ifdef OPENSSL + if (options & REFRESH_DES_KEY_FILE) + { + if (des_key_file) + result=load_des_key_file(des_key_file); + } +#endif return result; } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index ea105f3be50..e76998e9d7d 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -171,13 +171,14 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token DEMAND_SYM %token DESC %token DESCRIBE -%token DIRECTORY_SYM -%token DISTINCT +%token DES_KEY_FILE %token DISABLE_SYM +%token DISTINCT %token DYNAMIC_SYM %token ENABLE_SYM %token ENCLOSED %token ESCAPED +%token DIRECTORY_SYM %token ESCAPE_SYM %token EXISTS %token EXTENDED_SYM @@ -2106,13 +2107,7 @@ order_dir: limit_clause: - /* empty */ - { - SELECT_LEX *sel=Select; - sel->select_limit= (Lex->sql_command == SQLCOM_HA_READ) ? - 1 : current_thd->default_select_limit; - sel->offset_limit= 0L; - } + /* empty */ {} | LIMIT ULONG_NUM { SELECT_LEX *sel=Select; @@ -2511,13 +2506,14 @@ show_param: TEXT_STRING AND MASTER_LOG_POS_SYM EQ ulonglong_num AND MASTER_LOG_SEQ_SYM EQ ULONG_NUM AND MASTER_SERVER_ID_SYM EQ ULONG_NUM - { - Lex->sql_command = SQLCOM_SHOW_NEW_MASTER; - Lex->mi.log_file_name = $8.str; - Lex->mi.pos = $12; - Lex->mi.last_log_seq = $16; - Lex->mi.server_id = $20; - } + { + LEX *lex=Lex; + lex->sql_command = SQLCOM_SHOW_NEW_MASTER; + lex->mi.log_file_name = $8.str; + lex->mi.pos = $12; + lex->mi.last_log_seq = $16; + lex->mi.server_id = $20; + } | MASTER_SYM LOGS_SYM { Lex->sql_command = SQLCOM_SHOW_BINLOGS; @@ -2526,10 +2522,13 @@ show_param: { Lex->sql_command = SQLCOM_SHOW_SLAVE_HOSTS; } - | BINLOG_SYM EVENTS_SYM binlog_in binlog_from limit_clause + | BINLOG_SYM EVENTS_SYM binlog_in binlog_from { - Lex->sql_command = SQLCOM_SHOW_BINLOG_EVENTS; - } + LEX *lex=Lex; + lex->sql_command = SQLCOM_SHOW_BINLOG_EVENTS; + lex->select->select_limit= lex->thd->default_select_limit; + lex->select->offset_limit= 0L; + } limit_clause | keys_or_index FROM table_ident opt_db { Lex->sql_command= SQLCOM_SHOW_KEYS; @@ -2642,6 +2641,7 @@ flush_option: | STATUS_SYM { Lex->type|= REFRESH_STATUS; } | SLAVE { Lex->type|= REFRESH_SLAVE; } | MASTER_SYM { Lex->type|= REFRESH_MASTER; } + | DES_KEY_FILE { Lex->type|= REFRESH_DES_KEY_FILE; } opt_table_list: /* empty */ {} @@ -2912,27 +2912,28 @@ keyword: | CIPHER_SYM {} | CLOSE_SYM {} | COMMENT_SYM {} - | COMMIT_SYM {} | COMMITTED_SYM {} + | COMMIT_SYM {} | COMPRESSED_SYM {} | CONCURRENT {} | DATA_SYM {} | DATETIME {} | DATE_SYM {} | DAY_SYM {} - | DIRECTORY_SYM {} | DELAY_KEY_WRITE_SYM {} | DEMAND_SYM {} - | DISABLE_SYM {} + | DES_KEY_FILE {} + | DIRECTORY_SYM {} | DUMPFILE {} | DYNAMIC_SYM {} - | ENABLE_SYM {} | END {} | ENUM {} | ESCAPE_SYM {} | EVENTS_SYM {} | EXTENDED_SYM {} | FAST_SYM {} + | DISABLE_SYM {} + | ENABLE_SYM {} | FULL {} | FILE_SYM {} | FIRST_SYM {} @@ -3296,6 +3297,8 @@ handler: LEX *lex=Lex; lex->sql_command = SQLCOM_HA_READ; lex->ha_rkey_mode= HA_READ_KEY_EXACT; /* Avoid purify warnings */ + lex->select->select_limit= 1; + lex->select->offset_limit= 0L; if (!add_table_to_list($2,0,0)) YYABORT; } @@ -3581,9 +3584,8 @@ union_list: net_printf(&lex->thd->net, ER_WRONG_USAGE,"UNION","INTO"); YYABORT; } - if (lex->select->linkage == NOT_A_SELECT) + if (lex->select->linkage == NOT_A_SELECT || mysql_new_select(lex)) YYABORT; - mysql_new_select(lex); lex->select->linkage=UNION_TYPE; } select_init @@ -3597,11 +3599,11 @@ optional_order_or_limit: | { LEX *lex=Lex; - if (!lex->select->braces) - YYABORT; - mysql_new_select(lex); + if (!lex->select->braces || mysql_new_select(lex)) + YYABORT; mysql_init_select(lex); lex->select->linkage=NOT_A_SELECT; + lex->select->select_limit=lex->thd->default_select_limit; } opt_order_clause limit_clause |