diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index aadac36e2ee..414f9d52536 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2005, 2017, 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 @@ -624,7 +624,7 @@ int ha_partition::create(const char *name, TABLE *table_arg, int ha_partition::drop_partitions(const char *path) { List_iterator part_it(m_part_info->partitions); - char part_name_buff[FN_REFLEN]; + char part_name_buff[FN_REFLEN + 1]; uint num_parts= m_part_info->partitions.elements; uint num_subparts= m_part_info->num_subparts; uint i= 0; @@ -657,9 +657,12 @@ int ha_partition::drop_partitions(const char *path) { partition_element *sub_elem= sub_it++; part= i * num_subparts + j; - create_subpartition_name(part_name_buff, path, - part_elem->partition_name, - sub_elem->partition_name, name_variant); + if ((ret_error= create_subpartition_name(part_name_buff, path, + part_elem->partition_name, + sub_elem->partition_name, + name_variant))) + error= ret_error; + file= m_file[part]; DBUG_PRINT("info", ("Drop subpartition %s", part_name_buff)); if ((ret_error= file->ha_delete_table(part_name_buff))) @@ -670,9 +673,11 @@ int ha_partition::drop_partitions(const char *path) } else { - create_partition_name(part_name_buff, path, - part_elem->partition_name, name_variant, - TRUE); + if ((ret_error= create_partition_name(part_name_buff, path, + part_elem->partition_name, + name_variant, TRUE))) + error= ret_error; + file= m_file[i]; DBUG_PRINT("info", ("Drop partition %s", part_name_buff)); if ((ret_error= file->ha_delete_table(part_name_buff))) @@ -714,8 +719,8 @@ int ha_partition::rename_partitions(const char *path) { List_iterator part_it(m_part_info->partitions); List_iterator temp_it(m_part_info->temp_partitions); - char part_name_buff[FN_REFLEN]; - char norm_name_buff[FN_REFLEN]; + char part_name_buff[FN_REFLEN + 1]; + char norm_name_buff[FN_REFLEN + 1]; uint num_parts= m_part_info->partitions.elements; uint part_count= 0; uint num_subparts= m_part_info->num_subparts; @@ -757,10 +762,11 @@ int ha_partition::rename_partitions(const char *path) { sub_elem= sub_it++; file= m_reorged_file[part_count++]; - create_subpartition_name(norm_name_buff, path, - part_elem->partition_name, - sub_elem->partition_name, - NORMAL_PART_NAME); + if ((ret_error= create_subpartition_name(norm_name_buff, path, + part_elem->partition_name, + sub_elem->partition_name, + NORMAL_PART_NAME))) + error= ret_error; DBUG_PRINT("info", ("Delete subpartition %s", norm_name_buff)); if ((ret_error= file->ha_delete_table(norm_name_buff))) error= ret_error; @@ -773,9 +779,11 @@ int ha_partition::rename_partitions(const char *path) else { file= m_reorged_file[part_count++]; - create_partition_name(norm_name_buff, path, - part_elem->partition_name, NORMAL_PART_NAME, - TRUE); + if ((ret_error= create_partition_name(norm_name_buff, path, + part_elem->partition_name, + NORMAL_PART_NAME, TRUE))) + error= ret_error; + DBUG_PRINT("info", ("Delete partition %s", norm_name_buff)); if ((ret_error= file->ha_delete_table(norm_name_buff))) error= ret_error; @@ -825,10 +833,12 @@ int ha_partition::rename_partitions(const char *path) { sub_elem= sub_it++; part= i * num_subparts + j; - create_subpartition_name(norm_name_buff, path, - part_elem->partition_name, - sub_elem->partition_name, - NORMAL_PART_NAME); + if ((ret_error= create_subpartition_name(norm_name_buff, path, + part_elem->partition_name, + sub_elem->partition_name, + NORMAL_PART_NAME))) + error= ret_error; + if (part_elem->part_state == PART_IS_CHANGED) { file= m_reorged_file[part_count++]; @@ -840,10 +850,12 @@ int ha_partition::rename_partitions(const char *path) (void) sync_ddl_log(); } file= m_new_file[part]; - create_subpartition_name(part_name_buff, path, - part_elem->partition_name, - sub_elem->partition_name, - TEMP_PART_NAME); + if ((ret_error= create_subpartition_name(part_name_buff, path, + part_elem->partition_name, + sub_elem->partition_name, + TEMP_PART_NAME))) + error= ret_error; + DBUG_PRINT("info", ("Rename subpartition from %s to %s", part_name_buff, norm_name_buff)); if ((ret_error= file->ha_rename_table(part_name_buff, @@ -857,9 +869,11 @@ int ha_partition::rename_partitions(const char *path) } else { - create_partition_name(norm_name_buff, path, - part_elem->partition_name, NORMAL_PART_NAME, - TRUE); + if ((ret_error= create_partition_name(norm_name_buff, path, + part_elem->partition_name, + NORMAL_PART_NAME, TRUE))) + error= ret_error; + if (part_elem->part_state == PART_IS_CHANGED) { file= m_reorged_file[part_count++]; @@ -871,9 +885,11 @@ int ha_partition::rename_partitions(const char *path) (void) sync_ddl_log(); } file= m_new_file[i]; - create_partition_name(part_name_buff, path, - part_elem->partition_name, TEMP_PART_NAME, - TRUE); + if ((ret_error= create_partition_name(part_name_buff, path, + part_elem->partition_name, + TEMP_PART_NAME, TRUE))) + error= ret_error; + DBUG_PRINT("info", ("Rename partition from %s to %s", part_name_buff, norm_name_buff)); if ((ret_error= file->ha_rename_table(part_name_buff, @@ -1477,7 +1493,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, { List_iterator part_it(m_part_info->partitions); List_iterator t_it(m_part_info->temp_partitions); - char part_name_buff[FN_REFLEN]; + char part_name_buff[FN_REFLEN + 1]; uint num_parts= m_part_info->partitions.elements; uint num_subparts= m_part_info->num_subparts; uint i= 0; @@ -1687,10 +1703,15 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, do { partition_element *sub_elem= sub_it++; - create_subpartition_name(part_name_buff, path, - part_elem->partition_name, - sub_elem->partition_name, - name_variant); + if ((error= create_subpartition_name(part_name_buff, path, + part_elem->partition_name, + sub_elem->partition_name, + name_variant))) + { + cleanup_new_partition(part_count); + DBUG_RETURN(error); + } + part= i * num_subparts + j; DBUG_PRINT("info", ("Add subpartition %s", part_name_buff)); if ((error= prepare_new_partition(table, create_info, @@ -1708,9 +1729,14 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, } else { - create_partition_name(part_name_buff, path, - part_elem->partition_name, name_variant, - TRUE); + if ((error= create_partition_name(part_name_buff, path, + part_elem->partition_name, + name_variant, TRUE))) + { + cleanup_new_partition(part_count); + DBUG_RETURN(error); + } + DBUG_PRINT("info", ("Add partition %s", part_name_buff)); if ((error= prepare_new_partition(table, create_info, new_file_array[i], @@ -1967,8 +1993,8 @@ int ha_partition::del_ren_cre_table(const char *from, { int save_error= 0; int error= HA_ERR_INTERNAL_ERROR; - char from_buff[FN_REFLEN], to_buff[FN_REFLEN], from_lc_buff[FN_REFLEN], - to_lc_buff[FN_REFLEN], buff[FN_REFLEN]; + char from_buff[FN_REFLEN + 1], to_buff[FN_REFLEN + 1], from_lc_buff[FN_REFLEN + 1], + to_lc_buff[FN_REFLEN + 1], buff[FN_REFLEN + 1]; char *name_buffer_ptr; const char *from_path; const char *to_path= NULL; @@ -2015,13 +2041,16 @@ int ha_partition::del_ren_cre_table(const char *from, i= 0; do { - create_partition_name(from_buff, from_path, name_buffer_ptr, - NORMAL_PART_NAME, FALSE); + if ((error= create_partition_name(from_buff, from_path, name_buffer_ptr, + NORMAL_PART_NAME, FALSE))) + DBUG_RETURN(error); if (to != NULL) { // Rename branch - create_partition_name(to_buff, to_path, name_buffer_ptr, - NORMAL_PART_NAME, FALSE); + if ((error= create_partition_name(to_buff, to_path, name_buffer_ptr, + NORMAL_PART_NAME, FALSE))) + DBUG_RETURN(error); + error= (*file)->ha_rename_table(from_buff, to_buff); if (error) goto rename_error; @@ -2066,9 +2095,9 @@ create_error: name_buffer_ptr= m_name_buffer_ptr; for (abort_file= file, file= m_file; file < abort_file; file++) { - create_partition_name(from_buff, from_path, name_buffer_ptr, NORMAL_PART_NAME, - FALSE); - (void) (*file)->ha_delete_table((const char*) from_buff); + if (!create_partition_name(from_buff, from_path, name_buffer_ptr, NORMAL_PART_NAME, + FALSE)) + (void) (*file)->ha_delete_table((const char*) from_buff); name_buffer_ptr= strend(name_buffer_ptr) + 1; } DBUG_RETURN(error); @@ -2077,12 +2106,12 @@ rename_error: for (abort_file= file, file= m_file; file < abort_file; file++) { /* Revert the rename, back from 'to' to the original 'from' */ - create_partition_name(from_buff, from_path, name_buffer_ptr, - NORMAL_PART_NAME, FALSE); - create_partition_name(to_buff, to_path, name_buffer_ptr, - NORMAL_PART_NAME, FALSE); - /* Ignore error here */ - (void) (*file)->ha_rename_table(to_buff, from_buff); + if (!create_partition_name(from_buff, from_path, name_buffer_ptr, + NORMAL_PART_NAME, FALSE)) + if (!create_partition_name(to_buff, to_path, name_buffer_ptr, + NORMAL_PART_NAME, FALSE)) + /* Ignore error here */ + (void) (*file)->ha_rename_table(to_buff, from_buff); name_buffer_ptr= strend(name_buffer_ptr) + 1; } DBUG_RETURN(error); @@ -2707,7 +2736,7 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) char *name_buffer_ptr; int error= HA_ERR_INITIALIZATION; handler **file; - char name_buff[FN_REFLEN]; + char name_buff[FN_REFLEN + 1]; bool is_not_tmp_table= (table_share->tmp_table == NO_TMP_TABLE); ulonglong check_table_flags; DBUG_ENTER("ha_partition::open"); @@ -2777,8 +2806,10 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) file= m_is_clone_of->m_file; for (i= 0; i < m_tot_parts; i++) { - create_partition_name(name_buff, name, name_buffer_ptr, NORMAL_PART_NAME, - FALSE); + if ((error= create_partition_name(name_buff, name, name_buffer_ptr, + NORMAL_PART_NAME, FALSE))) + goto err_handler; + if (!(m_file[i]= file[i]->clone(name_buff, m_clone_mem_root))) { error= HA_ERR_INITIALIZATION; @@ -2793,8 +2824,9 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) file= m_file; do { - create_partition_name(name_buff, name, name_buffer_ptr, NORMAL_PART_NAME, - FALSE); + if ((error= create_partition_name(name_buff, name, name_buffer_ptr, + NORMAL_PART_NAME, FALSE))) + goto err_handler; if ((error= (*file)->ha_open(table, name_buff, mode, test_if_locked))) goto err_handler; m_num_locks+= (*file)->lock_count(); diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 5358535e9f9..65d4da0f2f6 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2005, 2017, 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 @@ -5958,8 +5958,8 @@ static bool write_log_changed_partitions(ALTER_PARTITION_PARAM_TYPE *lpt, DDL_LOG_ENTRY ddl_log_entry; partition_info *part_info= lpt->part_info; DDL_LOG_MEMORY_ENTRY *log_entry; - char tmp_path[FN_REFLEN]; - char normal_path[FN_REFLEN]; + char tmp_path[FN_REFLEN + 1]; + char normal_path[FN_REFLEN + 1]; List_iterator part_it(part_info->partitions); uint temp_partitions= part_info->temp_partitions.elements; uint num_elements= part_info->partitions.elements; @@ -5983,14 +5983,18 @@ static bool write_log_changed_partitions(ALTER_PARTITION_PARAM_TYPE *lpt, ddl_log_entry.next_entry= *next_entry; ddl_log_entry.handler_name= ha_resolve_storage_engine_name(sub_elem->engine_type); - create_subpartition_name(tmp_path, path, - part_elem->partition_name, - sub_elem->partition_name, - TEMP_PART_NAME); - create_subpartition_name(normal_path, path, - part_elem->partition_name, - sub_elem->partition_name, - NORMAL_PART_NAME); + if (create_subpartition_name(tmp_path, path, + part_elem->partition_name, + sub_elem->partition_name, + TEMP_PART_NAME)) + DBUG_RETURN(TRUE); + + if (create_subpartition_name(normal_path, path, + part_elem->partition_name, + sub_elem->partition_name, + NORMAL_PART_NAME)) + DBUG_RETURN(TRUE); + ddl_log_entry.name= normal_path; ddl_log_entry.from_name= tmp_path; if (part_elem->part_state == PART_IS_CHANGED) @@ -6011,12 +6015,13 @@ static bool write_log_changed_partitions(ALTER_PARTITION_PARAM_TYPE *lpt, ddl_log_entry.next_entry= *next_entry; ddl_log_entry.handler_name= ha_resolve_storage_engine_name(part_elem->engine_type); - create_partition_name(tmp_path, path, - part_elem->partition_name, - TEMP_PART_NAME, TRUE); - create_partition_name(normal_path, path, - part_elem->partition_name, - NORMAL_PART_NAME, TRUE); + if ((create_partition_name(tmp_path, path, part_elem->partition_name, + TEMP_PART_NAME, TRUE)) || + (create_partition_name(normal_path, path, + part_elem->partition_name, + NORMAL_PART_NAME, TRUE))) + DBUG_RETURN(TRUE); + ddl_log_entry.name= normal_path; ddl_log_entry.from_name= tmp_path; if (part_elem->part_state == PART_IS_CHANGED) @@ -6055,7 +6060,7 @@ static bool write_log_dropped_partitions(ALTER_PARTITION_PARAM_TYPE *lpt, DDL_LOG_ENTRY ddl_log_entry; partition_info *part_info= lpt->part_info; DDL_LOG_MEMORY_ENTRY *log_entry; - char tmp_path[FN_LEN]; + char tmp_path[FN_REFLEN + 1]; List_iterator part_it(part_info->partitions); List_iterator temp_it(part_info->temp_partitions); uint num_temp_partitions= part_info->temp_partitions.elements; @@ -6094,10 +6099,12 @@ static bool write_log_dropped_partitions(ALTER_PARTITION_PARAM_TYPE *lpt, ddl_log_entry.next_entry= *next_entry; ddl_log_entry.handler_name= ha_resolve_storage_engine_name(sub_elem->engine_type); - create_subpartition_name(tmp_path, path, - part_elem->partition_name, - sub_elem->partition_name, - name_variant); + if (create_subpartition_name(tmp_path, path, + part_elem->partition_name, + sub_elem->partition_name, + name_variant)) + DBUG_RETURN(TRUE); + ddl_log_entry.name= tmp_path; if (write_ddl_log_entry(&ddl_log_entry, &log_entry)) { @@ -6113,9 +6120,10 @@ static bool write_log_dropped_partitions(ALTER_PARTITION_PARAM_TYPE *lpt, ddl_log_entry.next_entry= *next_entry; ddl_log_entry.handler_name= ha_resolve_storage_engine_name(part_elem->engine_type); - create_partition_name(tmp_path, path, - part_elem->partition_name, - name_variant, TRUE); + if ((create_partition_name(tmp_path, path, part_elem->partition_name, + name_variant, TRUE))) + DBUG_RETURN(TRUE); + ddl_log_entry.name= tmp_path; if (write_ddl_log_entry(&ddl_log_entry, &log_entry)) { @@ -8194,29 +8202,28 @@ static uint32 get_next_subpartition_via_walking(PARTITION_ITERATOR *part_iter) } -/* - Create partition names +/** + Create partition names. This method is used to calculate the + partition name, service routine to the del_ren_cre_table method. + The output buffer size should be FN_REFLEN + 1(terminating '\0'). - SYNOPSIS - create_partition_name() - out:out Created partition name string - in1 First part - in2 Second part - name_variant Normal, temporary or renamed partition name + @param [out] out Created partition name string + @param in1 First part + @param in2 Second part + @param in3 Third part + @param name_variant Normal, temporary or renamed partition name + @param translate Flag to determine whether to convert a table name + to it its corresponding filename. - RETURN VALUE - NONE - - DESCRIPTION - This method is used to calculate the partition name, service routine to - the del_ren_cre_table method. + @retval true Error. + @retval false Success. */ -void create_partition_name(char *out, const char *in1, +bool create_partition_name(char *out, const char *in1, const char *in2, uint name_variant, bool translate) { - char transl_part_name[FN_REFLEN]; + char transl_part_name[FN_REFLEN + 1]; const char *transl_part; if (translate) @@ -8226,35 +8233,50 @@ void create_partition_name(char *out, const char *in1, } else transl_part= in2; + + // Check if the path name for partition exceeds maximum path length. if (name_variant == NORMAL_PART_NAME) - strxmov(out, in1, "#P#", transl_part, NullS); + { + if ((strlen(in1) + strlen(transl_part) + 3) > FN_REFLEN) + { + my_error(ER_PATH_LENGTH, MYF(0), in2); + return true; + } + } + else + if ((strlen(in1) + strlen(transl_part) + 8) > FN_REFLEN) + { + my_error(ER_PATH_LENGTH, MYF(0), in2); + return true; + } + + if (name_variant == NORMAL_PART_NAME) + strxnmov(out, FN_REFLEN, in1, "#P#", transl_part, NullS); else if (name_variant == TEMP_PART_NAME) - strxmov(out, in1, "#P#", transl_part, "#TMP#", NullS); + strxnmov(out, FN_REFLEN, in1, "#P#", transl_part, "#TMP#", NullS); else if (name_variant == RENAMED_PART_NAME) - strxmov(out, in1, "#P#", transl_part, "#REN#", NullS); + strxnmov(out, FN_REFLEN, in1, "#P#", transl_part, "#REN#", NullS); + + return false; } -/* - Create subpartition name +/** + Create subpartition name. This method is used to calculate the + subpartition name, service routine to the del_ren_cre_table method. + The output buffer size should be FN_REFLEN + 1(terminating '\0'). - SYNOPSIS - create_subpartition_name() - out:out Created partition name string - in1 First part - in2 Second part - in3 Third part - name_variant Normal, temporary or renamed partition name + @param [out] out Created partition name string + @param in1 First part + @param in2 Second part + @param in3 Third part + @param name_variant Normal, temporary or renamed partition name - RETURN VALUE - NONE - - DESCRIPTION - This method is used to calculate the subpartition name, service routine to - the del_ren_cre_table method. + @retval true Error. + @retval false Success. */ -void create_subpartition_name(char *out, const char *in1, +bool create_subpartition_name(char *out, const char *in1, const char *in2, const char *in3, uint name_variant) { @@ -8262,15 +8284,36 @@ void create_subpartition_name(char *out, const char *in1, tablename_to_filename(in2, transl_part_name, FN_REFLEN); tablename_to_filename(in3, transl_subpart_name, FN_REFLEN); + + // Check if the path name for subpartition exceeds maximum path length. if (name_variant == NORMAL_PART_NAME) - strxmov(out, in1, "#P#", transl_part_name, + { + if ((strlen(in1) + strlen(transl_part_name) + + strlen(transl_subpart_name) + 7) > FN_REFLEN) + { + my_error(ER_PATH_LENGTH, MYF(0), in3); + return true; + } + } + else + if ((strlen(in1) + strlen(transl_part_name) + + strlen(transl_subpart_name) + 12) > FN_REFLEN) + { + my_error(ER_PATH_LENGTH, MYF(0), in3); + return true; + } + + if (name_variant == NORMAL_PART_NAME) + strxnmov(out, FN_REFLEN, in1, "#P#", transl_part_name, "#SP#", transl_subpart_name, NullS); else if (name_variant == TEMP_PART_NAME) - strxmov(out, in1, "#P#", transl_part_name, + strxnmov(out, FN_REFLEN, in1, "#P#", transl_part_name, "#SP#", transl_subpart_name, "#TMP#", NullS); else if (name_variant == RENAMED_PART_NAME) - strxmov(out, in1, "#P#", transl_part_name, + strxnmov(out, FN_REFLEN, in1, "#P#", transl_part_name, "#SP#", transl_subpart_name, "#REN#", NullS); + + return false; } uint get_partition_field_store_length(Field *field) diff --git a/sql/sql_partition.h b/sql/sql_partition.h index f232eaa0629..cfaab903f04 100644 --- a/sql/sql_partition.h +++ b/sql/sql_partition.h @@ -1,7 +1,7 @@ #ifndef SQL_PARTITION_INCLUDED #define SQL_PARTITION_INCLUDED -/* Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2006, 2017, 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 @@ -272,10 +272,10 @@ char *generate_partition_syntax(partition_info *part_info, const char *current_comment_start); #endif -void create_partition_name(char *out, const char *in1, +bool create_partition_name(char *out, const char *in1, const char *in2, uint name_variant, bool translate); -void create_subpartition_name(char *out, const char *in1, +bool create_subpartition_name(char *out, const char *in1, const char *in2, const char *in3, uint name_variant);