GeezerVison is showing github.com — quic: fix UAF in Application::OnTimeout() · nodejs/node@a4db121
File tree
Expand file treeCollapse file tree
Open diff view settings
Expand file treeCollapse file tree
Open diff view settings
Collapse file
Copy file name to clipboardExpand all lines: src/quic/application.cc +8-6Lines changed: 8 additions & 6 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -369,12 +369,14 @@ void Session::Application::SendPendingData() { |
369 | 369 | if (closed) return; |
370 | 370 | // Flush any remaining accumulated packets before updating stats. |
371 | 371 | flush_batch(); |
372 | | - auto& s = session(); |
373 | | - if (!s.is_destroyed()) [[likely]] { |
374 | | - s.UpdatePacketTxTime(); |
375 | | - s.UpdateTimer(); |
376 | | - s.UpdateDataStats(); |
377 | | - } |
| 372 | + if (session().is_destroyed()) [[unlikely]] return; |
| 373 | + |
| 374 | + // Get a strong pointer to protect against potential destruction during |
| 375 | + // updating the time and data stats. |
| 376 | + BaseObjectPtr<Session> s(session_); |
| 377 | + s->UpdatePacketTxTime(); |
| 378 | + s->UpdateTimer(); |
| 379 | + s->UpdateDataStats(); |
378 | 380 | }); |
379 | 381 |
|
380 | 382 | // The maximum size of packet to create. |
|
Collapse file
Copy file name to clipboardExpand all lines: src/quic/session.cc +9Lines changed: 9 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -3026,6 +3026,15 @@ void Session::SendConnectionClose() { |
3026 | 3026 | void Session::OnTimeout() { |
3027 | 3027 | if (is_destroyed()) return; |
3028 | 3028 | if (!impl_->application_) return; |
| 3029 | + // Hold a strong reference to prevent the Session from being freed during |
| 3030 | + // re-entrant calls. SendPendingData's scope guard calls UpdateTimer(), |
| 3031 | + // which can synchronously re-enter OnTimeout() when the timer has already |
| 3032 | + // expired. That re-entrant path can reach FinishClose → EmitClose → |
| 3033 | + // Destroy → impl_.reset() → ~Impl → RemoveSession(), dropping the last |
| 3034 | + // BaseObjectPtr from the endpoint map and freeing the Session. Without |
| 3035 | + // this guard, the outer OnTimeout / SendPendingData frames would operate |
| 3036 | + // on a freed object. |
| 3037 | + BaseObjectPtr<Session> ref(this); |
3029 | 3038 | HandleScope scope(env()->isolate()); |
3030 | 3039 | int ret; |
3031 | 3040 | { |
|