Skip to content

Commit e6ea5d5

Browse files
FooBarriorsanja-byelkin
authored andcommitted
MDEV-36507 fix dbug_print_row concurrent access
7544fd4 had to make use of a static array to avoid memory use-after-free or leak. Instead, let us make a function returning String, this is the only way to automatically manage the memory after the function returned. To make it all correct, move constructor is added. Normally, it is expected, that the constructor will be elided upon return of an object by value, but if something goes different, or -fno-elide-constructors is used, we can have a problem. So this was a move constructor avoids copy elision-related UB. dbug_print_row returning char* is still there for convenient use in a debugger.
1 parent 4de5161 commit e6ea5d5

File tree

4 files changed

+43
-21
lines changed

4 files changed

+43
-21
lines changed

sql/filesort.cc

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -637,19 +637,8 @@ static uchar *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint count,
637637

638638
static char dbug_row_print_buf[4096];
639639

640-
/*
641-
Print table's current row into a buffer and return a pointer to it.
642-
643-
This is intended to be used from gdb:
644-
645-
(gdb) p dbug_print_table_row(table)
646-
$33 = "SUBQUERY2_t1(col_int_key,col_varchar_nokey)=(7,c)"
647-
(gdb)
648640

649-
Only columns in table->read_set are printed
650-
*/
651-
652-
const char* dbug_print_row(TABLE *table, const uchar *rec, bool print_names)
641+
String dbug_format_row(TABLE *table, const uchar *rec, bool print_names)
653642
{
654643
Field **pfield;
655644
char row_buff_tmp[512];
@@ -717,14 +706,37 @@ const char* dbug_print_row(TABLE *table, const uchar *rec, bool print_names)
717706
output.append(tmp.ptr(), tmp.length());
718707
}
719708
}
720-
output.append(")");
721-
if (output.c_ptr() == dbug_row_print_buf)
722-
return dbug_row_print_buf;
723-
else
709+
output.append(')');
710+
711+
return output;
712+
}
713+
714+
/**
715+
A function to display a row in debugger.
716+
717+
Example usage:
718+
(gdb) p dbug_print_row(table, table->record[1])
719+
*/
720+
const char *dbug_print_row(TABLE *table, const uchar *rec)
721+
{
722+
String row= dbug_format_row(table, table->record[0]);
723+
if (row.length() > sizeof dbug_row_print_buf - 1)
724724
return "Couldn't fit into buffer";
725+
memcpy(dbug_row_print_buf, row.c_ptr(), row.length());
726+
return dbug_row_print_buf;
725727
}
726728

729+
/**
730+
Print table's current row into a buffer and return a pointer to it.
731+
732+
This is intended to be used from gdb:
727733
734+
(gdb) p dbug_print_table_row(table)
735+
$33 = "SUBQUERY2_t1(col_int_key,col_varchar_nokey)=(7,c)"
736+
(gdb)
737+
738+
Only columns in table->read_set are printed
739+
*/
728740
const char* dbug_print_table_row(TABLE *table)
729741
{
730742
return dbug_print_row(table, table->record[0]);

sql/handler.cc

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7366,7 +7366,8 @@ int handler::ha_write_row(const uchar *buf)
73667366

73677367
TABLE_IO_WAIT(tracker, PSI_TABLE_WRITE_ROW, MAX_KEY, error,
73687368
{ error= write_row(buf); })
7369-
DBUG_PRINT("dml", ("INSERT: %s = %d", dbug_print_row(table, buf, false), error));
7369+
DBUG_PRINT("dml", ("INSERT: %s = %d",
7370+
dbug_format_row(table, buf, false).c_ptr_safe(), error));
73707371

73717372
MYSQL_INSERT_ROW_DONE(error);
73727373
if (likely(!error))
@@ -7425,8 +7426,10 @@ int handler::ha_update_row(const uchar *old_data, const uchar *new_data)
74257426

74267427
TABLE_IO_WAIT(tracker, PSI_TABLE_UPDATE_ROW, active_index, 0,
74277428
{ error= update_row(old_data, new_data);})
7428-
DBUG_PRINT("dml", ("UPDATE: %s => %s = %d", dbug_print_row(table, old_data, false),
7429-
dbug_print_row(table, new_data, false), error));
7429+
DBUG_PRINT("dml", ("UPDATE: %s => %s = %d",
7430+
dbug_format_row(table, old_data, false).c_ptr_safe(),
7431+
dbug_format_row(table, new_data, false).c_ptr_safe(),
7432+
error));
74307433

74317434
MYSQL_UPDATE_ROW_DONE(error);
74327435
if (likely(!error))
@@ -7506,7 +7509,8 @@ int handler::ha_delete_row(const uchar *buf)
75067509

75077510
TABLE_IO_WAIT(tracker, PSI_TABLE_DELETE_ROW, active_index, error,
75087511
{ error= delete_row(buf);})
7509-
DBUG_PRINT("dml", ("DELETE: %s = %d", dbug_print_row(table, buf, false), error));
7512+
DBUG_PRINT("dml", ("DELETE: %s = %d",
7513+
dbug_format_row(table, buf, false).c_ptr_safe(), error));
75107514
MYSQL_DELETE_ROW_DONE(error);
75117515
if (likely(!error))
75127516
{

sql/handler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5324,6 +5324,6 @@ int get_select_field_pos(Alter_info *alter_info, int select_field_count,
53245324
bool versioned);
53255325

53265326
#ifndef DBUG_OFF
5327-
const char* dbug_print_row(TABLE *table, const uchar *rec, bool print_names= true);
5327+
String dbug_format_row(TABLE *table, const uchar *rec, bool print_names= true);
53285328
#endif /* DBUG_OFF */
53295329
#endif /* HANDLER_INCLUDED */

sql/sql_string.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,10 @@ class Binary_string: public Static_binary_string
512512
extra_alloc= 0;
513513
alloced= thread_specific= 0;
514514
}
515+
Binary_string(Binary_string &&str) noexcept
516+
{
517+
move(str);
518+
}
515519

516520
~Binary_string() { free(); }
517521

@@ -856,6 +860,8 @@ class String: public Charset, public Binary_string
856860
Binary_string(str, len)
857861
{ }
858862
String(const String &str) = default;
863+
String(String &&str) noexcept
864+
:Charset(std::move(str)), Binary_string(std::move(str)){}
859865

860866
void set(String &str,size_t offset,size_t arg_length)
861867
{

0 commit comments

Comments
 (0)