———————————————————-
这里以一个简单的bug(bug#58198)为例,本例使用的也比较简单,就用SIGNAL 和WAIT_FOR
我们对Percona Server 5.5.18注入如下代码:
在函数mysql_change_db_impl(use db时会调用)中:
Index: sql/sql_db.cc =================================================================== --- sql/sql_db.cc (revision 1185) +++ sql/sql_db.cc (working copy) @@ -1291,7 +1291,7 @@ the previous database name, we should do it explicitly. */ my_free(thd->db); - + DEBUG_SYNC(thd, "use_db_free"); thd->reset_db(new_db_name->str, new_db_name->length); }
在函数mysqld_list_processes(show processlist时会调用)中:
Index: sql/sql_show.cc =================================================================== --- sql/sql_show.cc (revision 1185) +++ sql/sql_show.cc (working copy) @@ -1880,8 +1880,10 @@ thd_info->host= thd->strdup(tmp_sctx->host_or_ip[0] ? tmp_sctx->host_or_ip : tmp_sctx->host ? tmp_sctx->host : ""); - if ((thd_info->db=tmp->db)) // Safe test + if ((thd_info->db=tmp->db)) { // Safe test + DEBUG_SYNC(thd, "after_read_db_ptr"); thd_info->db=thd->strdup(thd_info->db); + } thd_info->command=(int) tmp->command; mysql_mutex_lock(&tmp->LOCK_thd_data); if ((mysys_var= tmp->mysys_var))
在show processlist时,在拷贝了tmp->db的指针后,有可能tmp->db所指向的内存已经被释放或被重用,这时候就在show processlist时就可能显示意料外的值,或者直接crash掉。。。。。
如下:
创建测试库
create database a;
create database abcde;
con1:
SET DEBUG_SYNC=’RESET'; —RESET表示重置DEBUG_SYNC
use a;
con2:
SET DEBUG_SYNC=’RESET';
SET DEBUG_SYNC=”after_read_db_ptr SIGNAL have_show WAIT_FOR have_free”;
—–当执行到 DEBUG_SYNC(thd, “after_read_db_ptr”)时会发送一个信号名为”have_show”,然后再等待信号名为”have_free”
show processlist;
—–发送“have_show”,等待“have_free”
con1:
SET DEBUG_SYNC=”now wait_for have_show”;
—-等待接收到信号”have_show”
SET DEBUG_SYNC=”use_db_free SIGNAL have_free WAIT_FOR finish_show”;
—-当执行到DEBUG_SYNC(thd, “use_db_free”)时,发送”have_free”信号,等待finish_show信号
use abcde;
—-发送have_free,等待finish_show
con2 :
SET DEBUG_SYNC=”now SIGNAL finish_show”;
—-发送finish_show信号