Skip to content

Commit fea02bb

Browse files
committed
Bug#19070633 - POSSIBLE ACCESS TO FREED MEMORY IN IS_FREE_LOCK()
AND IS_USED_LOCK(). Merging from 5.5 to 5.6.
2 parents 3f88b8e + 508c74a commit fea02bb

File tree

3 files changed

+122
-8
lines changed

3 files changed

+122
-8
lines changed

mysql-test/r/lock_sync.result

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -853,3 +853,54 @@ connection con2;
853853
#Clean up.
854854
DROP TABLE t1;
855855
SET DEBUG_SYNC= 'RESET';
856+
#
857+
# Bug#19070633 - POSSIBLE ACCESS TO FREED MEMORY IN IS_FREE_LOCK() AND IS_USED_LOCK().
858+
#
859+
# Verifying issue for IS_FREE_LOCK() function.
860+
SELECT GET_LOCK("lock_19070633", 600);
861+
GET_LOCK("lock_19070633", 600)
862+
1
863+
connect con1, localhost, root,,;
864+
# Waiting after getting user level lock info and releasing mutex.
865+
SET DEBUG_SYNC= 'after_getting_user_level_lock_info SIGNAL parked WAIT_FOR go';
866+
# Sending: SELECT IS_FREE_LOCK("lock_19070633");
867+
SELECT IS_FREE_LOCK("lock_19070633");
868+
connection default;
869+
SET DEBUG_SYNC= 'now WAIT_FOR parked';
870+
SELECT RELEASE_LOCK("lock_19070633");
871+
RELEASE_LOCK("lock_19070633")
872+
1
873+
# Signaling connection con1 after releasing the lock.
874+
# Without fix, accessing user level lock info in con1 would result in
875+
# crash or valgrind issue invalid read is reported.
876+
SET DEBUG_SYNC= 'now SIGNAL go';
877+
connection con1;
878+
# Reaping: SELECT IS_FREE_LOCK("lock_19070633");
879+
IS_FREE_LOCK("lock_19070633")
880+
0
881+
connection default;
882+
# Verifying issue for IS_USED_LOCK() function.
883+
SELECT GET_LOCK("lock_19070633", 600);
884+
GET_LOCK("lock_19070633", 600)
885+
1
886+
connection con1;
887+
# Waiting after getting user level lock info and releasing mutex.
888+
SET DEBUG_SYNC= 'after_getting_user_level_lock_info SIGNAL parked WAIT_FOR go';
889+
# Sending: SELECT IS_USED_LOCK("lock_19070633");
890+
SELECT IS_USED_LOCK("lock_19070633");
891+
connection default;
892+
SET DEBUG_SYNC= 'now WAIT_FOR parked';
893+
SELECT RELEASE_LOCK("lock_19070633");
894+
RELEASE_LOCK("lock_19070633")
895+
1
896+
# Signaling connection con1 after releasing the lock.
897+
# Without fix, accessing user level lock info in con1 would result in
898+
# crash or valgrind issue invalid read is reported.
899+
SET DEBUG_SYNC= 'now SIGNAL go';
900+
connection con1;
901+
# Reaping: SELECT IS_USED_LOCK("lock_19070633");
902+
IS_USED_LOCK("lock_19070633")
903+
#
904+
connection default;
905+
SET DEBUG_SYNC= 'RESET';
906+
disconnect con1;

mysql-test/t/lock_sync.test

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,6 +1242,62 @@ SET DEBUG_SYNC= 'RESET';
12421242
--disconnect con1
12431243

12441244

1245+
--echo #
1246+
--echo # Bug#19070633 - POSSIBLE ACCESS TO FREED MEMORY IN IS_FREE_LOCK() AND IS_USED_LOCK().
1247+
--echo #
1248+
1249+
--enable_connect_log
1250+
1251+
--echo # Verifying issue for IS_FREE_LOCK() function.
1252+
SELECT GET_LOCK("lock_19070633", 600);
1253+
1254+
connect (con1, localhost, root,,);
1255+
--echo # Waiting after getting user level lock info and releasing mutex.
1256+
SET DEBUG_SYNC= 'after_getting_user_level_lock_info SIGNAL parked WAIT_FOR go';
1257+
--echo # Sending: SELECT IS_FREE_LOCK("lock_19070633");
1258+
send SELECT IS_FREE_LOCK("lock_19070633");
1259+
1260+
connection default;
1261+
SET DEBUG_SYNC= 'now WAIT_FOR parked';
1262+
SELECT RELEASE_LOCK("lock_19070633");
1263+
--echo # Signaling connection con1 after releasing the lock.
1264+
--echo # Without fix, accessing user level lock info in con1 would result in
1265+
--echo # crash or valgrind issue invalid read is reported.
1266+
SET DEBUG_SYNC= 'now SIGNAL go';
1267+
1268+
connection con1;
1269+
--echo # Reaping: SELECT IS_FREE_LOCK("lock_19070633");
1270+
--reap
1271+
1272+
connection default;
1273+
--echo # Verifying issue for IS_USED_LOCK() function.
1274+
SELECT GET_LOCK("lock_19070633", 600);
1275+
1276+
connection con1;
1277+
--echo # Waiting after getting user level lock info and releasing mutex.
1278+
SET DEBUG_SYNC= 'after_getting_user_level_lock_info SIGNAL parked WAIT_FOR go';
1279+
--echo # Sending: SELECT IS_USED_LOCK("lock_19070633");
1280+
send SELECT IS_USED_LOCK("lock_19070633");
1281+
1282+
connection default;
1283+
SET DEBUG_SYNC= 'now WAIT_FOR parked';
1284+
SELECT RELEASE_LOCK("lock_19070633");
1285+
--echo # Signaling connection con1 after releasing the lock.
1286+
--echo # Without fix, accessing user level lock info in con1 would result in
1287+
--echo # crash or valgrind issue invalid read is reported.
1288+
SET DEBUG_SYNC= 'now SIGNAL go';
1289+
1290+
connection con1;
1291+
--echo # Reaping: SELECT IS_USED_LOCK("lock_19070633");
1292+
--replace_column 1 #
1293+
--reap
1294+
1295+
connection default;
1296+
SET DEBUG_SYNC= 'RESET';
1297+
disconnect con1;
1298+
1299+
--disable_connect_log
1300+
12451301
# Check that all connections opened by test cases in this file are really
12461302
# gone so execution of other tests won't be affected by their presence.
12471303
--source include/wait_until_count_sessions.inc

sql/item_func.cc

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6499,28 +6499,32 @@ longlong Item_func_is_free_lock::val_int()
64996499
DBUG_ASSERT(fixed == 1);
65006500
String *res=args[0]->val_str(&value);
65016501
User_level_lock *ull;
6502+
longlong ret_val= 0LL;
65026503

65036504
null_value=0;
65046505
if (!res || !res->length())
65056506
{
65066507
null_value=1;
6507-
return 0;
6508+
return ret_val;
65086509
}
65096510

65106511
mysql_mutex_lock(&LOCK_user_locks);
65116512
ull= (User_level_lock *) my_hash_search(&hash_user_locks, (uchar*) res->ptr(),
65126513
(size_t) res->length());
6513-
mysql_mutex_unlock(&LOCK_user_locks);
65146514
if (!ull || !ull->locked)
6515-
return 1;
6516-
return 0;
6515+
ret_val= 1;
6516+
mysql_mutex_unlock(&LOCK_user_locks);
6517+
DEBUG_SYNC(current_thd, "after_getting_user_level_lock_info");
6518+
6519+
return ret_val;
65176520
}
65186521

65196522
longlong Item_func_is_used_lock::val_int()
65206523
{
65216524
DBUG_ASSERT(fixed == 1);
65226525
String *res=args[0]->val_str(&value);
65236526
User_level_lock *ull;
6527+
my_thread_id thread_id= 0UL;
65246528

65256529
null_value=1;
65266530
if (!res || !res->length())
@@ -6529,12 +6533,15 @@ longlong Item_func_is_used_lock::val_int()
65296533
mysql_mutex_lock(&LOCK_user_locks);
65306534
ull= (User_level_lock *) my_hash_search(&hash_user_locks, (uchar*) res->ptr(),
65316535
(size_t) res->length());
6536+
if ((ull != NULL) && ull->locked)
6537+
{
6538+
null_value= 0;
6539+
thread_id= ull->thread_id;
6540+
}
65326541
mysql_mutex_unlock(&LOCK_user_locks);
6533-
if (!ull || !ull->locked)
6534-
return 0;
6542+
DEBUG_SYNC(current_thd, "after_getting_user_level_lock_info");
65356543

6536-
null_value=0;
6537-
return ull->thread_id;
6544+
return thread_id;
65386545
}
65396546

65406547

0 commit comments

Comments
 (0)