Handle null session in MoqtLivePublisher::OnNewObjectAvailable.

When a MoQT session is closing, visitor()->session() returns nullptr. Add a check to return early when the session is null to prevent null pointer dereferences.

PiperOrigin-RevId: 986962626
diff --git a/quiche/quic/moqt/moqt_live_publisher.cc b/quiche/quic/moqt/moqt_live_publisher.cc
index 0bdfb64..a67ddad 100644
--- a/quiche/quic/moqt/moqt_live_publisher.cc
+++ b/quiche/quic/moqt/moqt_live_publisher.cc
@@ -184,7 +184,7 @@
   // TODO(vasilvv): This currently sends UINT64_MAX for datagram subgroups.
   // Maybe do something more satisfactory?
   SessionToPublisherInterface* session_info = visitor();
-  if (session_info == nullptr) {
+  if (session_info == nullptr || session_info->session() == nullptr) {
     return;  // Session is gone.
   }
   session_info->trace_recorder().RecordNewObjectAvaliable(
diff --git a/quiche/quic/moqt/moqt_live_publisher_test.cc b/quiche/quic/moqt/moqt_live_publisher_test.cc
index d70fd0d..ed67d2a 100644
--- a/quiche/quic/moqt/moqt_live_publisher_test.cc
+++ b/quiche/quic/moqt/moqt_live_publisher_test.cc
@@ -732,6 +732,20 @@
   publisher_->OnSubgroupAbandoned(1, 0, 1234);
 }
 
+// Repro for b/565145319. A new object arrives while the session is closing.
+TEST_F(LivePublisherTest, OnNewObjectAvailableSessionClosing) {
+  CreateStream(Location(1, 0), 0, 128);
+  // When MoqtSession::is_closing_ is true, session() returns nullptr.
+  EXPECT_CALL(visitor_, session).WillRepeatedly(Return(nullptr));
+  EXPECT_CALL(*track_publisher_,
+              GetCachedObject(1, std::make_optional<uint64_t>(0), 1, 0))
+      .Times(testing::AtMost(1))
+      .WillOnce(Return(DefaultPublishedObject(Location(1, 1), 0, 128)));
+  EXPECT_CALL(monitoring_interface_, OnNewObjectEnqueued(Location(1, 1)))
+      .Times(testing::AtMost(1));
+  publisher_->OnNewObjectAvailable(Location(1, 1), 0, 128);
+}
+
 }  // namespace
 
 }  // namespace moqt::test