Allocate LogMessageData from LowLevelAlloc and lazily construct its ostream.

When LOG(...) or LOG(FATAL) is invoked from inside a MallocHook callback (such
as in MallocDetector or ThreadLocalMallocHook), allocating LogMessageData via
operator new or destroying an unused std::ostream in ~LogMessageData (which
calls free(nullptr) in libc++'s ios_base::~ios_base) reenters the memory
allocator.

Allocate LogMessageData from an unhooked LowLevelAlloc arena and wrap
LogMessageData::manipulated in std::optional<std::ostream> so the stream is
constructed only when OstreamView is actually used. Also use ABSL_RAW_LOG in
logging_unittest's MallocHook test callback.
PiperOrigin-RevId: 1002204028
diff --git a/absl/log/CMakeLists.txt b/absl/log/CMakeLists.txt
index 1da38e4..13fbd09 100644
--- a/absl/log/CMakeLists.txt
+++ b/absl/log/CMakeLists.txt
@@ -211,6 +211,7 @@
     absl::log_severity
     absl::log_sink
     absl::log_sink_registry
+    absl::malloc_internal
     absl::memory
     absl::nullability
     absl::raw_logging_internal
diff --git a/absl/log/internal/BUILD.bazel b/absl/log/internal/BUILD.bazel
index 42114ed..202e257 100644
--- a/absl/log/internal/BUILD.bazel
+++ b/absl/log/internal/BUILD.bazel
@@ -208,6 +208,7 @@
         "//absl/base:core_headers",
         "//absl/base:errno_saver",
         "//absl/base:log_severity",
+        "//absl/base:malloc_internal",
         "//absl/base:nullability",
         "//absl/base:raw_logging_internal",
         "//absl/base:strerror",
diff --git a/absl/log/internal/log_message.cc b/absl/log/internal/log_message.cc
index e56ef25..9b63217 100644
--- a/absl/log/internal/log_message.cc
+++ b/absl/log/internal/log_message.cc
@@ -25,12 +25,15 @@
 #include <atomic>
 #include <ios>
 #include <memory>
+#include <optional>
 #include <ostream>
 #include <string>
 #include <string_view>
 
 #include "absl/base/attributes.h"
+#include "absl/base/call_once.h"
 #include "absl/base/config.h"
+#include "absl/base/internal/low_level_alloc.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/internal/strerror.h"
 #include "absl/base/internal/sysinfo.h"
@@ -145,6 +148,17 @@
   auto* cast_os = static_cast<std::ostream*>(os);
   *cast_os << data;
 }
+
+#ifndef ABSL_LOW_LEVEL_ALLOC_MISSING
+absl::base_internal::LowLevelAlloc::Arena* LogMessageArena() {
+  ABSL_CONST_INIT static absl::once_flag once;
+  ABSL_CONST_INIT static absl::base_internal::LowLevelAlloc::Arena* arena =
+      nullptr;
+  absl::base_internal::LowLevelCallOnce(
+      &once, []() { arena = absl::base_internal::LowLevelAlloc::NewArena(0); });
+  return arena;
+}
+#endif
 }  // namespace
 
 struct LogMessage::LogMessageData final {
@@ -153,6 +167,16 @@
   LogMessageData(const LogMessageData&) = delete;
   LogMessageData& operator=(const LogMessageData&) = delete;
 
+#ifndef ABSL_LOW_LEVEL_ALLOC_MISSING
+  static void* operator new(size_t s) {
+    return absl::base_internal::LowLevelAlloc::AllocWithArena(
+        s, LogMessageArena());
+  }
+  static void operator delete(void* p) {
+    absl::base_internal::LowLevelAlloc::Free(p);
+  }
+#endif
+
   // `LogEntry` sent to `LogSink`s; contains metadata.
   absl::LogEntry entry;
 
@@ -169,7 +193,8 @@
   // non-sink targets (e.g. stderr, log files).
   bool extra_sinks_only;
 
-  std::ostream manipulated;  // ostream with IO manipulators applied
+  std::optional<std::ostream> manipulated;  // Lazily constructed ostream
+                                            // with IO manipulators applied
 
   // A `logging.proto.Event` proto message is built into `encoded_buf`.
   std::array<char, kLogMessageBufferSize> encoded_buf;
@@ -200,12 +225,10 @@
   void FinalizeEncodingAndFormat();
 };
 
-LogMessage::LogMessageData::LogMessageData(absl::string_view file,
-                                           int line, absl::LogSeverity severity,
+LogMessage::LogMessageData::LogMessageData(absl::string_view file, int line,
+                                           absl::LogSeverity severity,
                                            absl::Time timestamp)
-    : extra_sinks_only(false), manipulated(nullptr) {
-  // Legacy defaults for LOG's ostream:
-  manipulated.setf(std::ios_base::showbase | std::ios_base::boolalpha);
+    : extra_sinks_only(false) {
   entry.full_filename_ = file;
   entry.base_filename_ = Basename(file);
   entry.line_ = line;
@@ -439,12 +462,12 @@
 
 LogMessage& LogMessage::operator<<(std::ostream& (*m)(std::ostream& os)) {
   OstreamView view(*data_);
-  data_->manipulated << m;
+  view.stream() << m;
   return *this;
 }
 LogMessage& LogMessage::operator<<(std::ios_base& (*m)(std::ios_base& os)) {
   OstreamView view(*data_);
-  data_->manipulated << m;
+  view.stream() << m;
   return *this;
 }
 // NOLINTBEGIN(runtime/int)
@@ -501,6 +524,11 @@
 
 LogMessage::OstreamView::OstreamView(LogMessageData& message_data)
     : data_(message_data), encoded_remaining_copy_(data_.encoded_remaining()) {
+  if (!data_.manipulated.has_value()) {
+    data_.manipulated.emplace(nullptr);
+    // Legacy defaults for LOG's ostream:
+    data_.manipulated->setf(std::ios_base::showbase | std::ios_base::boolalpha);
+  }
   // This constructor sets the `streambuf` up so that streaming into an attached
   // ostream encodes string data in-place.  To do that, we write appropriate
   // headers into the buffer using a copy of the buffer view so that we can
@@ -515,11 +543,11 @@
                          &encoded_remaining_copy_);
   setp(encoded_remaining_copy_.data(),
        encoded_remaining_copy_.data() + encoded_remaining_copy_.size());
-  data_.manipulated.rdbuf(this);
+  data_.manipulated->rdbuf(this);
 }
 
 LogMessage::OstreamView::~OstreamView() {
-  data_.manipulated.rdbuf(nullptr);
+  data_.manipulated->rdbuf(nullptr);
   if (!string_start_.data()) {
     // The second field header didn't fit.  Whether the first one did or not, we
     // shouldn't commit `encoded_remaining_copy_`, and we also need to zero the
@@ -536,7 +564,7 @@
   data_.encoded_remaining() = encoded_remaining_copy_;
 }
 
-std::ostream& LogMessage::OstreamView::stream() { return data_.manipulated; }
+std::ostream& LogMessage::OstreamView::stream() { return *data_.manipulated; }
 
 bool LogMessage::IsFatal() const {
   return data_->entry.log_severity() == absl::LogSeverity::kFatal &&