Commit 277af61c by Abseil Team Committed by Copybara-Service

Fix out of bounds array access when deadlock detector finds exceptionally large cycles.

PiperOrigin-RevId: 511536497
Change-Id: If70a1c72ef5f7cbb4a80100c4edff459373a5d55
parent d6ea4df6
...@@ -1403,7 +1403,7 @@ static GraphId DeadlockCheck(Mutex *mu) { ...@@ -1403,7 +1403,7 @@ static GraphId DeadlockCheck(Mutex *mu) {
ABSL_RAW_LOG(ERROR, "Cycle: "); ABSL_RAW_LOG(ERROR, "Cycle: ");
int path_len = deadlock_graph->FindPath( int path_len = deadlock_graph->FindPath(
mu_id, other_node_id, ABSL_ARRAYSIZE(b->path), b->path); mu_id, other_node_id, ABSL_ARRAYSIZE(b->path), b->path);
for (int j = 0; j != path_len; j++) { for (int j = 0; j != path_len && j != ABSL_ARRAYSIZE(b->path); j++) {
GraphId id = b->path[j]; GraphId id = b->path[j];
Mutex *path_mu = static_cast<Mutex *>(deadlock_graph->Ptr(id)); Mutex *path_mu = static_cast<Mutex *>(deadlock_graph->Ptr(id));
if (path_mu == nullptr) continue; if (path_mu == nullptr) continue;
...@@ -1416,6 +1416,9 @@ static GraphId DeadlockCheck(Mutex *mu) { ...@@ -1416,6 +1416,9 @@ static GraphId DeadlockCheck(Mutex *mu) {
symbolize); symbolize);
ABSL_RAW_LOG(ERROR, "%s", b->buf); ABSL_RAW_LOG(ERROR, "%s", b->buf);
} }
if (path_len > static_cast<int>(ABSL_ARRAYSIZE(b->path))) {
ABSL_RAW_LOG(ERROR, "(long cycle; list truncated)");
}
if (synch_deadlock_detection.load(std::memory_order_acquire) == if (synch_deadlock_detection.load(std::memory_order_acquire) ==
OnDeadlockCycle::kAbort) { OnDeadlockCycle::kAbort) {
deadlock_graph_mu.Unlock(); // avoid deadlock in fatal sighandler deadlock_graph_mu.Unlock(); // avoid deadlock in fatal sighandler
......
...@@ -1131,6 +1131,25 @@ TEST(Mutex, DeadlockDetectorBazelWarning) { ...@@ -1131,6 +1131,25 @@ TEST(Mutex, DeadlockDetectorBazelWarning) {
absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort); absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort);
} }
TEST(Mutex, DeadlockDetectorLongCycle) {
absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kReport);
// This test generates a warning if it passes, and crashes otherwise.
// Cause bazel to ignore the warning.
ScopedDisableBazelTestWarnings disable_bazel_test_warnings;
// Check that we survive a deadlock with a lock cycle.
std::vector<absl::Mutex> mutex(100);
for (size_t i = 0; i != mutex.size(); i++) {
mutex[i].Lock();
mutex[(i + 1) % mutex.size()].Lock();
mutex[i].Unlock();
mutex[(i + 1) % mutex.size()].Unlock();
}
absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort);
}
// This test is tagged with NO_THREAD_SAFETY_ANALYSIS because the // This test is tagged with NO_THREAD_SAFETY_ANALYSIS because the
// annotation-based static thread-safety analysis is not currently // annotation-based static thread-safety analysis is not currently
// predicate-aware and cannot tell if the two for-loops that acquire and // predicate-aware and cannot tell if the two for-loops that acquire and
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment