Loading sql/field.cc +14 −10 Original line number Diff line number Diff line Loading @@ -4254,7 +4254,7 @@ Field_timestamp::Field_timestamp(char *ptr_arg, uint32 len_arg, const char *field_name_arg, struct st_table *table_arg, CHARSET_INFO *cs) :Field_str(ptr_arg, 19, null_ptr_arg, null_bit_arg, :Field_str(ptr_arg, MAX_DATETIME_WIDTH, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, table_arg, cs) { /* For 4.0 MYD and 4.0 InnoDB compatibility */ Loading @@ -4272,7 +4272,8 @@ Field_timestamp::Field_timestamp(char *ptr_arg, uint32 len_arg, Field_timestamp::Field_timestamp(bool maybe_null_arg, const char *field_name_arg, struct st_table *table_arg, CHARSET_INFO *cs) :Field_str((char*) 0, 19, maybe_null_arg ? (uchar*) "": 0, 0, :Field_str((char*) 0, MAX_DATETIME_WIDTH, maybe_null_arg ? (uchar*) "": 0, 0, NONE, field_name_arg, table_arg, cs) { /* For 4.0 MYD and 4.0 InnoDB compatibility */ Loading Loading @@ -4803,7 +4804,7 @@ String *Field_time::val_str(String *val_buffer, String *val_ptr __attribute__((unused))) { MYSQL_TIME ltime; val_buffer->alloc(19); val_buffer->alloc(MAX_DATE_STRING_REP_LENGTH); long tmp=(long) sint3korr(ptr); ltime.neg= 0; if (tmp < 0) Loading Loading @@ -5339,7 +5340,7 @@ int Field_newdate::store_time(MYSQL_TIME *ltime, timestamp_type time_type) (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE | MODE_INVALID_DATES))), &error)) { char buff[12]; char buff[MAX_DATE_STRING_REP_LENGTH]; String str(buff, sizeof(buff), &my_charset_latin1); make_date((DATE_TIME_FORMAT *) 0, ltime, &str); set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, Loading Loading @@ -5564,7 +5565,7 @@ int Field_datetime::store_time(MYSQL_TIME *ltime,timestamp_type time_type) (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE | MODE_INVALID_DATES))), &error)) { char buff[19]; char buff[MAX_DATE_STRING_REP_LENGTH]; String str(buff, sizeof(buff), &my_charset_latin1); make_datetime((DATE_TIME_FORMAT *) 0, ltime, &str); set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, Loading Loading @@ -5638,7 +5639,7 @@ String *Field_datetime::val_str(String *val_buffer, part1=(long) (tmp/LL(1000000)); part2=(long) (tmp - (ulonglong) part1*LL(1000000)); pos=(char*) val_buffer->ptr()+19; pos= (char*) val_buffer->ptr() + MAX_DATETIME_WIDTH; *pos--=0; *pos--= (char) ('0'+(char) (part2%10)); part2/=10; *pos--= (char) ('0'+(char) (part2%10)); part3= (int) (part2 / 10); Loading Loading @@ -8536,15 +8537,18 @@ bool create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, break; case FIELD_TYPE_TIMESTAMP: if (!fld_length) length= 14; /* Full date YYYYMMDDHHMMSS */ else if (length != 19) { /* Compressed date YYYYMMDDHHMMSS */ length= MAX_DATETIME_COMPRESSED_WIDTH; } else if (length != MAX_DATETIME_WIDTH) { /* We support only even TIMESTAMP lengths less or equal than 14 and 19 as length of 4.1 compatible representation. */ length= ((length+1)/2)*2; /* purecov: inspected */ length= min(length,14); /* purecov: inspected */ length= min(length, MAX_DATETIME_COMPRESSED_WIDTH); /* purecov: inspected */ } flags|= ZEROFILL_FLAG | UNSIGNED_FLAG; if (fld_default_value) Loading Loading @@ -8597,7 +8601,7 @@ bool create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, length= 10; break; case FIELD_TYPE_DATETIME: length= 19; length= MAX_DATETIME_WIDTH; break; case FIELD_TYPE_SET: { Loading sql/item_timefunc.cc +21 −11 Original line number Diff line number Diff line Loading @@ -51,7 +51,7 @@ static bool make_datetime(date_time_format_types format, MYSQL_TIME *ltime, { char *buff; CHARSET_INFO *cs= &my_charset_bin; uint length= 30; uint length= MAX_DATE_STRING_REP_LENGTH; if (str->alloc(length)) return 1; Loading Loading @@ -1400,7 +1400,7 @@ String *Item_date::val_str(String *str) MYSQL_TIME ltime; if (get_date(<ime, TIME_FUZZY_DATE)) return (String *) 0; if (str->alloc(11)) if (str->alloc(MAX_DATE_STRING_REP_LENGTH)) { null_value= 1; return (String *) 0; Loading Loading @@ -1449,7 +1449,7 @@ void Item_func_curdate::fix_length_and_dec() String *Item_func_curdate::val_str(String *str) { DBUG_ASSERT(fixed == 1); if (str->alloc(11)) if (str->alloc(MAX_DATE_STRING_REP_LENGTH)) { null_value= 1; return (String *) 0; Loading Loading @@ -1678,7 +1678,8 @@ String *Item_func_sec_to_time::val_str(String *str) MYSQL_TIME ltime; longlong arg_val= args[0]->val_int(); if ((null_value=args[0]->null_value) || str->alloc(19)) if ((null_value=args[0]->null_value) || str->alloc(MAX_DATE_STRING_REP_LENGTH)) { null_value= 1; return (String*) 0; Loading Loading @@ -1863,6 +1864,10 @@ String *Item_func_date_format::val_str(String *str) size=max_length; else size=format_length(format); if (size < MAX_DATE_STRING_REP_LENGTH) size= MAX_DATE_STRING_REP_LENGTH; if (format == str) str= &value; // Save result here if (str->alloc(size)) Loading Loading @@ -1906,13 +1911,14 @@ String *Item_func_from_unixtime::val_str(String *str) if (get_date(&time_tmp, 0)) return 0; if (str->alloc(20*MY_CHARSET_BIN_MB_MAXLEN)) if (str->alloc(MAX_DATE_STRING_REP_LENGTH)) { null_value= 1; return 0; } make_datetime((DATE_TIME_FORMAT *) 0, &time_tmp, str); return str; } Loading Loading @@ -1975,13 +1981,14 @@ String *Item_func_convert_tz::val_str(String *str) if (get_date(&time_tmp, 0)) return 0; if (str->alloc(20*MY_CHARSET_BIN_MB_MAXLEN)) if (str->alloc(MAX_DATE_STRING_REP_LENGTH)) { null_value= 1; return 0; } make_datetime((DATE_TIME_FORMAT *) 0, &time_tmp, str); return str; } Loading Loading @@ -2561,6 +2568,7 @@ String *Item_datetime_typecast::val_str(String *str) { DBUG_ASSERT(fixed == 1); MYSQL_TIME ltime; if (!get_arg0_date(<ime, TIME_FUZZY_DATE) && !make_datetime(ltime.second_part ? DATE_TIME_MICROSECOND : DATE_TIME, <ime, str)) Loading Loading @@ -2639,7 +2647,8 @@ String *Item_date_typecast::val_str(String *str) DBUG_ASSERT(fixed == 1); MYSQL_TIME ltime; if (!get_arg0_date(<ime, TIME_FUZZY_DATE) && !str->alloc(11)) if (!get_arg0_date(<ime, TIME_FUZZY_DATE) && !str->alloc(MAX_DATE_STRING_REP_LENGTH)) { make_date((DATE_TIME_FORMAT *) 0, <ime, str); return str; Loading Loading @@ -2692,7 +2701,7 @@ String *Item_func_makedate::val_str(String *str) { null_value=0; get_date_from_daynr(days,&l_time.year,&l_time.month,&l_time.day); if (str->alloc(11)) if (str->alloc(MAX_DATE_STRING_REP_LENGTH)) goto err; make_date((DATE_TIME_FORMAT *) 0, &l_time, str); return str; Loading Loading @@ -2828,6 +2837,7 @@ String *Item_func_add_time::val_str(String *str) days= (long)(seconds/86400L); calc_time_from_sec(&l_time3, (long)(seconds%86400L), microseconds); if (!is_time) { get_date_from_daynr(days,&l_time3.year,&l_time3.month,&l_time3.day); Loading Loading @@ -2943,7 +2953,7 @@ String *Item_func_maketime::val_str(String *str) args[2]->null_value || minute < 0 || minute > 59 || second < 0 || second > 59 || str->alloc(19)))) str->alloc(MAX_DATE_STRING_REP_LENGTH)))) return 0; bzero((char *)<ime, sizeof(ltime)); Loading sql/unireg.h +1 −0 Original line number Diff line number Diff line Loading @@ -71,6 +71,7 @@ #define MAX_TIME_WIDTH 23 /* -DDDDDD HH:MM:SS.###### */ #define MAX_DATETIME_FULL_WIDTH 29 /* YYYY-MM-DD HH:MM:SS.###### AM */ #define MAX_DATETIME_WIDTH 19 /* YYYY-MM-DD HH:MM:SS */ #define MAX_DATETIME_COMPRESSED_WIDTH 14 /* YYYYMMDDHHMMSS */ #define MAX_TABLES (sizeof(table_map)*8-3) /* Max tables in join */ #define PARAM_TABLE_BIT (((table_map) 1) << (sizeof(table_map)*8-3)) Loading tests/mysql_client_test.c +54 −0 Original line number Diff line number Diff line Loading @@ -15623,6 +15623,59 @@ static void test_bug27876() } /* Bug#27592 (stack overrun when storing datetime value using prepared statements) */ static void test_bug27592() { const int NUM_ITERATIONS= 40; int i; int rc; MYSQL_STMT *stmt= NULL; MYSQL_BIND bind[1]; MYSQL_TIME time_val; DBUG_ENTER("test_bug27592"); myheader("test_bug27592"); mysql_query(mysql, "DROP TABLE IF EXISTS t1"); mysql_query(mysql, "CREATE TABLE t1(c2 DATETIME)"); stmt= mysql_simple_prepare(mysql, "INSERT INTO t1 VALUES (?)"); DIE_UNLESS(stmt); memset(bind, 0, sizeof(bind)); bind[0].buffer_type= MYSQL_TYPE_DATETIME; bind[0].buffer= (char *) &time_val; bind[0].length= NULL; for (i= 0; i < NUM_ITERATIONS; i++) { time_val.year= 2007; time_val.month= 6; time_val.day= 7; time_val.hour= 18; time_val.minute= 41; time_val.second= 3; time_val.second_part=0; time_val.neg=0; rc= mysql_stmt_bind_param(stmt, bind); check_execute(stmt, rc); rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); } mysql_stmt_close(stmt); DBUG_VOID_RETURN; } /* Read and parse arguments and MySQL options from my.cnf */ Loading Loading @@ -15904,6 +15957,7 @@ static struct my_tests_st my_tests[]= { { "test_bug21635", test_bug21635 }, { "test_bug24179", test_bug24179 }, { "test_bug27876", test_bug27876 }, { "test_bug27592", test_bug27592 }, { 0, 0 } }; Loading Loading
sql/field.cc +14 −10 Original line number Diff line number Diff line Loading @@ -4254,7 +4254,7 @@ Field_timestamp::Field_timestamp(char *ptr_arg, uint32 len_arg, const char *field_name_arg, struct st_table *table_arg, CHARSET_INFO *cs) :Field_str(ptr_arg, 19, null_ptr_arg, null_bit_arg, :Field_str(ptr_arg, MAX_DATETIME_WIDTH, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, table_arg, cs) { /* For 4.0 MYD and 4.0 InnoDB compatibility */ Loading @@ -4272,7 +4272,8 @@ Field_timestamp::Field_timestamp(char *ptr_arg, uint32 len_arg, Field_timestamp::Field_timestamp(bool maybe_null_arg, const char *field_name_arg, struct st_table *table_arg, CHARSET_INFO *cs) :Field_str((char*) 0, 19, maybe_null_arg ? (uchar*) "": 0, 0, :Field_str((char*) 0, MAX_DATETIME_WIDTH, maybe_null_arg ? (uchar*) "": 0, 0, NONE, field_name_arg, table_arg, cs) { /* For 4.0 MYD and 4.0 InnoDB compatibility */ Loading Loading @@ -4803,7 +4804,7 @@ String *Field_time::val_str(String *val_buffer, String *val_ptr __attribute__((unused))) { MYSQL_TIME ltime; val_buffer->alloc(19); val_buffer->alloc(MAX_DATE_STRING_REP_LENGTH); long tmp=(long) sint3korr(ptr); ltime.neg= 0; if (tmp < 0) Loading Loading @@ -5339,7 +5340,7 @@ int Field_newdate::store_time(MYSQL_TIME *ltime, timestamp_type time_type) (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE | MODE_INVALID_DATES))), &error)) { char buff[12]; char buff[MAX_DATE_STRING_REP_LENGTH]; String str(buff, sizeof(buff), &my_charset_latin1); make_date((DATE_TIME_FORMAT *) 0, ltime, &str); set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, Loading Loading @@ -5564,7 +5565,7 @@ int Field_datetime::store_time(MYSQL_TIME *ltime,timestamp_type time_type) (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE | MODE_INVALID_DATES))), &error)) { char buff[19]; char buff[MAX_DATE_STRING_REP_LENGTH]; String str(buff, sizeof(buff), &my_charset_latin1); make_datetime((DATE_TIME_FORMAT *) 0, ltime, &str); set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, Loading Loading @@ -5638,7 +5639,7 @@ String *Field_datetime::val_str(String *val_buffer, part1=(long) (tmp/LL(1000000)); part2=(long) (tmp - (ulonglong) part1*LL(1000000)); pos=(char*) val_buffer->ptr()+19; pos= (char*) val_buffer->ptr() + MAX_DATETIME_WIDTH; *pos--=0; *pos--= (char) ('0'+(char) (part2%10)); part2/=10; *pos--= (char) ('0'+(char) (part2%10)); part3= (int) (part2 / 10); Loading Loading @@ -8536,15 +8537,18 @@ bool create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, break; case FIELD_TYPE_TIMESTAMP: if (!fld_length) length= 14; /* Full date YYYYMMDDHHMMSS */ else if (length != 19) { /* Compressed date YYYYMMDDHHMMSS */ length= MAX_DATETIME_COMPRESSED_WIDTH; } else if (length != MAX_DATETIME_WIDTH) { /* We support only even TIMESTAMP lengths less or equal than 14 and 19 as length of 4.1 compatible representation. */ length= ((length+1)/2)*2; /* purecov: inspected */ length= min(length,14); /* purecov: inspected */ length= min(length, MAX_DATETIME_COMPRESSED_WIDTH); /* purecov: inspected */ } flags|= ZEROFILL_FLAG | UNSIGNED_FLAG; if (fld_default_value) Loading Loading @@ -8597,7 +8601,7 @@ bool create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, length= 10; break; case FIELD_TYPE_DATETIME: length= 19; length= MAX_DATETIME_WIDTH; break; case FIELD_TYPE_SET: { Loading
sql/item_timefunc.cc +21 −11 Original line number Diff line number Diff line Loading @@ -51,7 +51,7 @@ static bool make_datetime(date_time_format_types format, MYSQL_TIME *ltime, { char *buff; CHARSET_INFO *cs= &my_charset_bin; uint length= 30; uint length= MAX_DATE_STRING_REP_LENGTH; if (str->alloc(length)) return 1; Loading Loading @@ -1400,7 +1400,7 @@ String *Item_date::val_str(String *str) MYSQL_TIME ltime; if (get_date(<ime, TIME_FUZZY_DATE)) return (String *) 0; if (str->alloc(11)) if (str->alloc(MAX_DATE_STRING_REP_LENGTH)) { null_value= 1; return (String *) 0; Loading Loading @@ -1449,7 +1449,7 @@ void Item_func_curdate::fix_length_and_dec() String *Item_func_curdate::val_str(String *str) { DBUG_ASSERT(fixed == 1); if (str->alloc(11)) if (str->alloc(MAX_DATE_STRING_REP_LENGTH)) { null_value= 1; return (String *) 0; Loading Loading @@ -1678,7 +1678,8 @@ String *Item_func_sec_to_time::val_str(String *str) MYSQL_TIME ltime; longlong arg_val= args[0]->val_int(); if ((null_value=args[0]->null_value) || str->alloc(19)) if ((null_value=args[0]->null_value) || str->alloc(MAX_DATE_STRING_REP_LENGTH)) { null_value= 1; return (String*) 0; Loading Loading @@ -1863,6 +1864,10 @@ String *Item_func_date_format::val_str(String *str) size=max_length; else size=format_length(format); if (size < MAX_DATE_STRING_REP_LENGTH) size= MAX_DATE_STRING_REP_LENGTH; if (format == str) str= &value; // Save result here if (str->alloc(size)) Loading Loading @@ -1906,13 +1911,14 @@ String *Item_func_from_unixtime::val_str(String *str) if (get_date(&time_tmp, 0)) return 0; if (str->alloc(20*MY_CHARSET_BIN_MB_MAXLEN)) if (str->alloc(MAX_DATE_STRING_REP_LENGTH)) { null_value= 1; return 0; } make_datetime((DATE_TIME_FORMAT *) 0, &time_tmp, str); return str; } Loading Loading @@ -1975,13 +1981,14 @@ String *Item_func_convert_tz::val_str(String *str) if (get_date(&time_tmp, 0)) return 0; if (str->alloc(20*MY_CHARSET_BIN_MB_MAXLEN)) if (str->alloc(MAX_DATE_STRING_REP_LENGTH)) { null_value= 1; return 0; } make_datetime((DATE_TIME_FORMAT *) 0, &time_tmp, str); return str; } Loading Loading @@ -2561,6 +2568,7 @@ String *Item_datetime_typecast::val_str(String *str) { DBUG_ASSERT(fixed == 1); MYSQL_TIME ltime; if (!get_arg0_date(<ime, TIME_FUZZY_DATE) && !make_datetime(ltime.second_part ? DATE_TIME_MICROSECOND : DATE_TIME, <ime, str)) Loading Loading @@ -2639,7 +2647,8 @@ String *Item_date_typecast::val_str(String *str) DBUG_ASSERT(fixed == 1); MYSQL_TIME ltime; if (!get_arg0_date(<ime, TIME_FUZZY_DATE) && !str->alloc(11)) if (!get_arg0_date(<ime, TIME_FUZZY_DATE) && !str->alloc(MAX_DATE_STRING_REP_LENGTH)) { make_date((DATE_TIME_FORMAT *) 0, <ime, str); return str; Loading Loading @@ -2692,7 +2701,7 @@ String *Item_func_makedate::val_str(String *str) { null_value=0; get_date_from_daynr(days,&l_time.year,&l_time.month,&l_time.day); if (str->alloc(11)) if (str->alloc(MAX_DATE_STRING_REP_LENGTH)) goto err; make_date((DATE_TIME_FORMAT *) 0, &l_time, str); return str; Loading Loading @@ -2828,6 +2837,7 @@ String *Item_func_add_time::val_str(String *str) days= (long)(seconds/86400L); calc_time_from_sec(&l_time3, (long)(seconds%86400L), microseconds); if (!is_time) { get_date_from_daynr(days,&l_time3.year,&l_time3.month,&l_time3.day); Loading Loading @@ -2943,7 +2953,7 @@ String *Item_func_maketime::val_str(String *str) args[2]->null_value || minute < 0 || minute > 59 || second < 0 || second > 59 || str->alloc(19)))) str->alloc(MAX_DATE_STRING_REP_LENGTH)))) return 0; bzero((char *)<ime, sizeof(ltime)); Loading
sql/unireg.h +1 −0 Original line number Diff line number Diff line Loading @@ -71,6 +71,7 @@ #define MAX_TIME_WIDTH 23 /* -DDDDDD HH:MM:SS.###### */ #define MAX_DATETIME_FULL_WIDTH 29 /* YYYY-MM-DD HH:MM:SS.###### AM */ #define MAX_DATETIME_WIDTH 19 /* YYYY-MM-DD HH:MM:SS */ #define MAX_DATETIME_COMPRESSED_WIDTH 14 /* YYYYMMDDHHMMSS */ #define MAX_TABLES (sizeof(table_map)*8-3) /* Max tables in join */ #define PARAM_TABLE_BIT (((table_map) 1) << (sizeof(table_map)*8-3)) Loading
tests/mysql_client_test.c +54 −0 Original line number Diff line number Diff line Loading @@ -15623,6 +15623,59 @@ static void test_bug27876() } /* Bug#27592 (stack overrun when storing datetime value using prepared statements) */ static void test_bug27592() { const int NUM_ITERATIONS= 40; int i; int rc; MYSQL_STMT *stmt= NULL; MYSQL_BIND bind[1]; MYSQL_TIME time_val; DBUG_ENTER("test_bug27592"); myheader("test_bug27592"); mysql_query(mysql, "DROP TABLE IF EXISTS t1"); mysql_query(mysql, "CREATE TABLE t1(c2 DATETIME)"); stmt= mysql_simple_prepare(mysql, "INSERT INTO t1 VALUES (?)"); DIE_UNLESS(stmt); memset(bind, 0, sizeof(bind)); bind[0].buffer_type= MYSQL_TYPE_DATETIME; bind[0].buffer= (char *) &time_val; bind[0].length= NULL; for (i= 0; i < NUM_ITERATIONS; i++) { time_val.year= 2007; time_val.month= 6; time_val.day= 7; time_val.hour= 18; time_val.minute= 41; time_val.second= 3; time_val.second_part=0; time_val.neg=0; rc= mysql_stmt_bind_param(stmt, bind); check_execute(stmt, rc); rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); } mysql_stmt_close(stmt); DBUG_VOID_RETURN; } /* Read and parse arguments and MySQL options from my.cnf */ Loading Loading @@ -15904,6 +15957,7 @@ static struct my_tests_st my_tests[]= { { "test_bug21635", test_bug21635 }, { "test_bug24179", test_bug24179 }, { "test_bug27876", test_bug27876 }, { "test_bug27592", test_bug27592 }, { 0, 0 } }; Loading