1 //
2 // Copyright 2022 The Abseil Authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      https://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #include "absl/log/internal/log_message.h"
17 
18 #include <stddef.h>
19 #include <stdint.h>
20 #include <stdlib.h>
21 #include <string.h>
22 
23 #ifndef _WIN32
24 #include <unistd.h>
25 #endif
26 
27 #include <algorithm>
28 #include <array>
29 #include <atomic>
30 #include <memory>
31 #include <ostream>
32 #include <string>
33 #include <tuple>
34 
35 #include "absl/base/attributes.h"
36 #include "absl/base/config.h"
37 #include "absl/base/internal/raw_logging.h"
38 #include "absl/base/internal/strerror.h"
39 #include "absl/base/internal/sysinfo.h"
40 #include "absl/base/log_severity.h"
41 #include "absl/container/inlined_vector.h"
42 #include "absl/debugging/internal/examine_stack.h"
43 #include "absl/log/globals.h"
44 #include "absl/log/internal/append_truncated.h"
45 #include "absl/log/internal/globals.h"
46 #include "absl/log/internal/log_format.h"
47 #include "absl/log/internal/log_sink_set.h"
48 #include "absl/log/internal/proto.h"
49 #include "absl/log/log_entry.h"
50 #include "absl/log/log_sink.h"
51 #include "absl/log/log_sink_registry.h"
52 #include "absl/memory/memory.h"
53 #include "absl/strings/string_view.h"
54 #include "absl/time/clock.h"
55 #include "absl/time/time.h"
56 #include "absl/types/span.h"
57 
ABSL_INTERNAL_C_SYMBOL(AbslInternalOnFatalLogMessage)58 extern "C" ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(
59     AbslInternalOnFatalLogMessage)(const absl::LogEntry&) {
60   // Default - Do nothing
61 }
62 
63 namespace absl {
64 ABSL_NAMESPACE_BEGIN
65 namespace log_internal {
66 
67 namespace {
68 // message `logging.proto.Event`
69 enum EventTag : uint8_t {
70   kValue = 7,
71 };
72 
73 // message `logging.proto.Value`
74 enum ValueTag : uint8_t {
75   kString = 1,
76   kStringLiteral = 6,
77 };
78 
79 // Decodes a `logging.proto.Value` from `buf` and writes a string representation
80 // into `dst`.  The string representation will be truncated if `dst` is not
81 // large enough to hold it.  Returns false if `dst` has size zero or one (i.e.
82 // sufficient only for a nul-terminator) and no decoded data could be written.
83 // This function may or may not write a nul-terminator into `dst`, and it may or
84 // may not truncate the data it writes in order to do make space for that nul
85 // terminator.  In any case, `dst` will be advanced to point at the byte where
86 // subsequent writes should begin.
PrintValue(absl::Span<char> & dst,absl::Span<const char> buf)87 bool PrintValue(absl::Span<char>& dst, absl::Span<const char> buf) {
88   if (dst.size() <= 1) return false;
89   ProtoField field;
90   while (field.DecodeFrom(&buf)) {
91     switch (field.tag()) {
92       case ValueTag::kString:
93       case ValueTag::kStringLiteral:
94         if (field.type() == WireType::kLengthDelimited)
95           if (log_internal::AppendTruncated(field.string_value(), dst) <
96               field.string_value().size())
97             return false;
98     }
99   }
100   return true;
101 }
102 
Basename(absl::string_view filepath)103 absl::string_view Basename(absl::string_view filepath) {
104 #ifdef _WIN32
105   size_t path = filepath.find_last_of("/\\");
106 #else
107   size_t path = filepath.find_last_of('/');
108 #endif
109   if (path != filepath.npos) filepath.remove_prefix(path + 1);
110   return filepath;
111 }
112 
WriteToString(const char * data,void * str)113 void WriteToString(const char* data, void* str) {
114   reinterpret_cast<std::string*>(str)->append(data);
115 }
WriteToStream(const char * data,void * os)116 void WriteToStream(const char* data, void* os) {
117   auto* cast_os = static_cast<std::ostream*>(os);
118   *cast_os << data;
119 }
120 }  // namespace
121 
122 struct LogMessage::LogMessageData final {
123   LogMessageData(const char* file, int line, absl::LogSeverity severity,
124                  absl::Time timestamp);
125   LogMessageData(const LogMessageData&) = delete;
126   LogMessageData& operator=(const LogMessageData&) = delete;
127 
128   // `LogEntry` sent to `LogSink`s; contains metadata.
129   absl::LogEntry entry;
130 
131   // true => this was first fatal msg
132   bool first_fatal;
133   // true => all failures should be quiet
134   bool fail_quietly;
135   // true => PLOG was requested
136   bool is_perror;
137 
138   // Extra `LogSink`s to log to, in addition to `global_sinks`.
139   absl::InlinedVector<absl::LogSink*, 16> extra_sinks;
140   // If true, log to `extra_sinks` but not to `global_sinks` or hardcoded
141   // non-sink targets (e.g. stderr, log files).
142   bool extra_sinks_only;
143 
144   std::ostream manipulated;  // ostream with IO manipulators applied
145 
146   // A `logging.proto.Event` proto message is built into `encoded_buf`.
147   std::array<char, kLogMessageBufferSize> encoded_buf;
148   // `encoded_remaining` is the suffix of `encoded_buf` that has not been filled
149   // yet.  If a datum to be encoded does not fit into `encoded_remaining` and
150   // cannot be truncated to fit, the size of `encoded_remaining` will be zeroed
151   // to prevent encoding of any further data.  Note that in this case its data()
152   // pointer will not point past the end of `encoded_buf`.
153   absl::Span<char> encoded_remaining;
154 
155   // A formatted string message is built in `string_buf`.
156   std::array<char, kLogMessageBufferSize> string_buf;
157 
158   void FinalizeEncodingAndFormat();
159 };
160 
LogMessageData(const char * file,int line,absl::LogSeverity severity,absl::Time timestamp)161 LogMessage::LogMessageData::LogMessageData(const char* file, int line,
162                                            absl::LogSeverity severity,
163                                            absl::Time timestamp)
164     : extra_sinks_only(false),
165       manipulated(nullptr),
166       // This `absl::MakeSpan` silences spurious -Wuninitialized from GCC:
167       encoded_remaining(absl::MakeSpan(encoded_buf)) {
168   // Legacy defaults for LOG's ostream:
169   manipulated.setf(std::ios_base::showbase | std::ios_base::boolalpha);
170   entry.full_filename_ = file;
171   entry.base_filename_ = Basename(file);
172   entry.line_ = line;
173   entry.prefix_ = absl::ShouldPrependLogPrefix();
174   entry.severity_ = absl::NormalizeLogSeverity(severity);
175   entry.verbose_level_ = absl::LogEntry::kNoVerbosityLevel;
176   entry.timestamp_ = timestamp;
177   entry.tid_ = absl::base_internal::GetCachedTID();
178 }
179 
FinalizeEncodingAndFormat()180 void LogMessage::LogMessageData::FinalizeEncodingAndFormat() {
181   // Note that `encoded_remaining` may have zero size without pointing past the
182   // end of `encoded_buf`, so the difference between `data()` pointers is used
183   // to compute the size of `encoded_data`.
184   absl::Span<const char> encoded_data(
185       encoded_buf.data(),
186       static_cast<size_t>(encoded_remaining.data() - encoded_buf.data()));
187   // `string_remaining` is the suffix of `string_buf` that has not been filled
188   // yet.
189   absl::Span<char> string_remaining(string_buf);
190   // We may need to write a newline and nul-terminator at the end of the decoded
191   // string data.  Rather than worry about whether those should overwrite the
192   // end of the string (if the buffer is full) or be appended, we avoid writing
193   // into the last two bytes so we always have space to append.
194   string_remaining.remove_suffix(2);
195   entry.prefix_len_ =
196       entry.prefix() ? log_internal::FormatLogPrefix(
197                            entry.log_severity(), entry.timestamp(), entry.tid(),
198                            entry.source_basename(), entry.source_line(),
199                            log_internal::ThreadIsLoggingToLogSink()
200                                ? PrefixFormat::kRaw
201                                : PrefixFormat::kNotRaw,
202                            string_remaining)
203                      : 0;
204   // Decode data from `encoded_buf` until we run out of data or we run out of
205   // `string_remaining`.
206   ProtoField field;
207   while (field.DecodeFrom(&encoded_data)) {
208     switch (field.tag()) {
209       case EventTag::kValue:
210         if (field.type() != WireType::kLengthDelimited) continue;
211         if (PrintValue(string_remaining, field.bytes_value())) continue;
212         break;
213     }
214     break;
215   }
216   auto chars_written =
217       static_cast<size_t>(string_remaining.data() - string_buf.data());
218     string_buf[chars_written++] = '\n';
219   string_buf[chars_written++] = '\0';
220   entry.text_message_with_prefix_and_newline_and_nul_ =
221       absl::MakeSpan(string_buf).subspan(0, chars_written);
222 }
223 
LogMessage(const char * file,int line,absl::LogSeverity severity)224 LogMessage::LogMessage(const char* file, int line, absl::LogSeverity severity)
225     : data_(absl::make_unique<LogMessageData>(file, line, severity,
226                                               absl::Now())) {
227   data_->first_fatal = false;
228   data_->is_perror = false;
229   data_->fail_quietly = false;
230 
231   // This logs a backtrace even if the location is subsequently changed using
232   // AtLocation.  This quirk, and the behavior when AtLocation is called twice,
233   // are fixable but probably not worth fixing.
234   LogBacktraceIfNeeded();
235 }
236 
~LogMessage()237 LogMessage::~LogMessage() {
238 #ifdef ABSL_MIN_LOG_LEVEL
239   if (data_->entry.log_severity() <
240           static_cast<absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) &&
241       data_->entry.log_severity() < absl::LogSeverity::kFatal) {
242     return;
243   }
244 #endif
245   Flush();
246 }
247 
AtLocation(absl::string_view file,int line)248 LogMessage& LogMessage::AtLocation(absl::string_view file, int line) {
249   data_->entry.full_filename_ = file;
250   data_->entry.base_filename_ = Basename(file);
251   data_->entry.line_ = line;
252   LogBacktraceIfNeeded();
253   return *this;
254 }
255 
NoPrefix()256 LogMessage& LogMessage::NoPrefix() {
257   data_->entry.prefix_ = false;
258   return *this;
259 }
260 
WithVerbosity(int verbose_level)261 LogMessage& LogMessage::WithVerbosity(int verbose_level) {
262   if (verbose_level == absl::LogEntry::kNoVerbosityLevel) {
263     data_->entry.verbose_level_ = absl::LogEntry::kNoVerbosityLevel;
264   } else {
265     data_->entry.verbose_level_ = std::max(0, verbose_level);
266   }
267   return *this;
268 }
269 
WithTimestamp(absl::Time timestamp)270 LogMessage& LogMessage::WithTimestamp(absl::Time timestamp) {
271   data_->entry.timestamp_ = timestamp;
272   return *this;
273 }
274 
WithThreadID(absl::LogEntry::tid_t tid)275 LogMessage& LogMessage::WithThreadID(absl::LogEntry::tid_t tid) {
276   data_->entry.tid_ = tid;
277   return *this;
278 }
279 
WithMetadataFrom(const absl::LogEntry & entry)280 LogMessage& LogMessage::WithMetadataFrom(const absl::LogEntry& entry) {
281   data_->entry.full_filename_ = entry.full_filename_;
282   data_->entry.base_filename_ = entry.base_filename_;
283   data_->entry.line_ = entry.line_;
284   data_->entry.prefix_ = entry.prefix_;
285   data_->entry.severity_ = entry.severity_;
286   data_->entry.verbose_level_ = entry.verbose_level_;
287   data_->entry.timestamp_ = entry.timestamp_;
288   data_->entry.tid_ = entry.tid_;
289   return *this;
290 }
291 
WithPerror()292 LogMessage& LogMessage::WithPerror() {
293   data_->is_perror = true;
294   return *this;
295 }
296 
ToSinkAlso(absl::LogSink * sink)297 LogMessage& LogMessage::ToSinkAlso(absl::LogSink* sink) {
298   ABSL_INTERNAL_CHECK(sink, "null LogSink*");
299   data_->extra_sinks.push_back(sink);
300   return *this;
301 }
302 
ToSinkOnly(absl::LogSink * sink)303 LogMessage& LogMessage::ToSinkOnly(absl::LogSink* sink) {
304   ABSL_INTERNAL_CHECK(sink, "null LogSink*");
305   data_->extra_sinks.clear();
306   data_->extra_sinks.push_back(sink);
307   data_->extra_sinks_only = true;
308   return *this;
309 }
310 
311 #ifdef __ELF__
312 extern "C" void __gcov_dump() ABSL_ATTRIBUTE_WEAK;
313 extern "C" void __gcov_flush() ABSL_ATTRIBUTE_WEAK;
314 #endif
315 
FailWithoutStackTrace()316 void LogMessage::FailWithoutStackTrace() {
317   // Now suppress repeated trace logging:
318   log_internal::SetSuppressSigabortTrace(true);
319 #if defined _DEBUG && defined COMPILER_MSVC
320   // When debugging on windows, avoid the obnoxious dialog.
321   __debugbreak();
322 #endif
323 
324 #ifdef __ELF__
325   // For b/8737634, flush coverage if we are in coverage mode.
326   if (&__gcov_dump != nullptr) {
327     __gcov_dump();
328   } else if (&__gcov_flush != nullptr) {
329     __gcov_flush();
330   }
331 #endif
332 
333   abort();
334 }
335 
FailQuietly()336 void LogMessage::FailQuietly() {
337   // _exit. Calling abort() would trigger all sorts of death signal handlers
338   // and a detailed stack trace. Calling exit() would trigger the onexit
339   // handlers, including the heap-leak checker, which is guaranteed to fail in
340   // this case: we probably just new'ed the std::string that we logged.
341   // Anyway, if you're calling Fail or FailQuietly, you're trying to bail out
342   // of the program quickly, and it doesn't make much sense for FailQuietly to
343   // offer different guarantees about exit behavior than Fail does. (And as a
344   // consequence for QCHECK and CHECK to offer different exit behaviors)
345   _exit(1);
346 }
347 
operator <<(const std::string & v)348 LogMessage& LogMessage::operator<<(const std::string& v) {
349   CopyToEncodedBuffer(v, StringType::kNotLiteral);
350   return *this;
351 }
352 
operator <<(absl::string_view v)353 LogMessage& LogMessage::operator<<(absl::string_view v) {
354   CopyToEncodedBuffer(v, StringType::kNotLiteral);
355   return *this;
356 }
operator <<(std::ostream & (* m)(std::ostream & os))357 LogMessage& LogMessage::operator<<(std::ostream& (*m)(std::ostream& os)) {
358   OstreamView view(*data_);
359   data_->manipulated << m;
360   return *this;
361 }
operator <<(std::ios_base & (* m)(std::ios_base & os))362 LogMessage& LogMessage::operator<<(std::ios_base& (*m)(std::ios_base& os)) {
363   OstreamView view(*data_);
364   data_->manipulated << m;
365   return *this;
366 }
367 template LogMessage& LogMessage::operator<<(const char& v);
368 template LogMessage& LogMessage::operator<<(const signed char& v);
369 template LogMessage& LogMessage::operator<<(const unsigned char& v);
370 template LogMessage& LogMessage::operator<<(const short& v);           // NOLINT
371 template LogMessage& LogMessage::operator<<(const unsigned short& v);  // NOLINT
372 template LogMessage& LogMessage::operator<<(const int& v);
373 template LogMessage& LogMessage::operator<<(const unsigned int& v);
374 template LogMessage& LogMessage::operator<<(const long& v);           // NOLINT
375 template LogMessage& LogMessage::operator<<(const unsigned long& v);  // NOLINT
376 template LogMessage& LogMessage::operator<<(const long long& v);      // NOLINT
377 template LogMessage& LogMessage::operator<<(
378     const unsigned long long& v);  // NOLINT
379 template LogMessage& LogMessage::operator<<(void* const& v);
380 template LogMessage& LogMessage::operator<<(const void* const& v);
381 template LogMessage& LogMessage::operator<<(const float& v);
382 template LogMessage& LogMessage::operator<<(const double& v);
383 template LogMessage& LogMessage::operator<<(const bool& v);
384 
Flush()385 void LogMessage::Flush() {
386   if (data_->entry.log_severity() < absl::MinLogLevel())
387     return;
388 
389   if (data_->is_perror) {
390     InternalStream() << ": " << absl::base_internal::StrError(errno_saver_())
391                      << " [" << errno_saver_() << "]";
392   }
393 
394   // Have we already seen a fatal message?
395   ABSL_CONST_INIT static std::atomic<bool> seen_fatal(false);
396   if (data_->entry.log_severity() == absl::LogSeverity::kFatal &&
397       absl::log_internal::ExitOnDFatal()) {
398     // Exactly one LOG(FATAL) message is responsible for aborting the process,
399     // even if multiple threads LOG(FATAL) concurrently.
400     bool expected_seen_fatal = false;
401     if (seen_fatal.compare_exchange_strong(expected_seen_fatal, true,
402                                            std::memory_order_relaxed)) {
403       data_->first_fatal = true;
404     }
405   }
406 
407   data_->FinalizeEncodingAndFormat();
408   data_->entry.encoding_ =
409       absl::string_view(data_->encoded_buf.data(),
410                         static_cast<size_t>(data_->encoded_remaining.data() -
411                                             data_->encoded_buf.data()));
412   SendToLog();
413 }
414 
SetFailQuietly()415 void LogMessage::SetFailQuietly() { data_->fail_quietly = true; }
416 
OstreamView(LogMessageData & message_data)417 LogMessage::OstreamView::OstreamView(LogMessageData& message_data)
418     : data_(message_data), encoded_remaining_copy_(data_.encoded_remaining) {
419   // This constructor sets the `streambuf` up so that streaming into an attached
420   // ostream encodes string data in-place.  To do that, we write appropriate
421   // headers into the buffer using a copy of the buffer view so that we can
422   // decide not to keep them later if nothing is ever streamed in.  We don't
423   // know how much data we'll get, but we can use the size of the remaining
424   // buffer as an upper bound and fill in the right size once we know it.
425   message_start_ =
426       EncodeMessageStart(EventTag::kValue, encoded_remaining_copy_.size(),
427                          &encoded_remaining_copy_);
428   string_start_ =
429       EncodeMessageStart(ValueTag::kString, encoded_remaining_copy_.size(),
430                        &encoded_remaining_copy_);
431   setp(encoded_remaining_copy_.data(),
432        encoded_remaining_copy_.data() + encoded_remaining_copy_.size());
433   data_.manipulated.rdbuf(this);
434 }
435 
~OstreamView()436 LogMessage::OstreamView::~OstreamView() {
437   data_.manipulated.rdbuf(nullptr);
438   if (!string_start_.data()) {
439     // The second field header didn't fit.  Whether the first one did or not, we
440     // shouldn't commit `encoded_remaining_copy_`, and we also need to zero the
441     // size of `data_->encoded_remaining` so that no more data are encoded.
442     data_.encoded_remaining.remove_suffix(data_.encoded_remaining.size());
443     return;
444   }
445   const absl::Span<const char> contents(pbase(),
446                                         static_cast<size_t>(pptr() - pbase()));
447   if (contents.empty()) return;
448   encoded_remaining_copy_.remove_prefix(contents.size());
449   EncodeMessageLength(string_start_, &encoded_remaining_copy_);
450   EncodeMessageLength(message_start_, &encoded_remaining_copy_);
451   data_.encoded_remaining = encoded_remaining_copy_;
452 }
453 
stream()454 std::ostream& LogMessage::OstreamView::stream() { return data_.manipulated; }
455 
IsFatal() const456 bool LogMessage::IsFatal() const {
457   return data_->entry.log_severity() == absl::LogSeverity::kFatal &&
458          absl::log_internal::ExitOnDFatal();
459 }
460 
PrepareToDie()461 void LogMessage::PrepareToDie() {
462   // If we log a FATAL message, flush all the log destinations, then toss
463   // a signal for others to catch. We leave the logs in a state that
464   // someone else can use them (as long as they flush afterwards)
465   if (data_->first_fatal) {
466     // Notify observers about the upcoming fatal error.
467     ABSL_INTERNAL_C_SYMBOL(AbslInternalOnFatalLogMessage)(data_->entry);
468   }
469 
470   if (!data_->fail_quietly) {
471     // Log the message first before we start collecting stack trace.
472     log_internal::LogToSinks(data_->entry, absl::MakeSpan(data_->extra_sinks),
473                              data_->extra_sinks_only);
474 
475     // `DumpStackTrace` generates an empty string under MSVC.
476     // Adding the constant prefix here simplifies testing.
477     data_->entry.stacktrace_ = "*** Check failure stack trace: ***\n";
478     debugging_internal::DumpStackTrace(
479         0, log_internal::MaxFramesInLogStackTrace(),
480         log_internal::ShouldSymbolizeLogStackTrace(), WriteToString,
481         &data_->entry.stacktrace_);
482   }
483 }
484 
Die()485 void LogMessage::Die() {
486   absl::FlushLogSinks();
487 
488   if (data_->fail_quietly) {
489     FailQuietly();
490   } else {
491     FailWithoutStackTrace();
492   }
493 }
494 
SendToLog()495 void LogMessage::SendToLog() {
496   if (IsFatal()) PrepareToDie();
497   // Also log to all registered sinks, even if OnlyLogToStderr() is set.
498   log_internal::LogToSinks(data_->entry, absl::MakeSpan(data_->extra_sinks),
499                            data_->extra_sinks_only);
500   if (IsFatal()) Die();
501 }
502 
LogBacktraceIfNeeded()503 void LogMessage::LogBacktraceIfNeeded() {
504   if (!absl::log_internal::IsInitialized()) return;
505 
506   if (!absl::log_internal::ShouldLogBacktraceAt(data_->entry.source_basename(),
507                                                 data_->entry.source_line()))
508     return;
509   OstreamView view(*data_);
510   view.stream() << " (stacktrace:\n";
511   debugging_internal::DumpStackTrace(
512       1, log_internal::MaxFramesInLogStackTrace(),
513       log_internal::ShouldSymbolizeLogStackTrace(), WriteToStream,
514       &view.stream());
515   view.stream() << ") ";
516 }
517 
518 // Encodes into `data_->encoded_remaining` a partial `logging.proto.Event`
519 // containing the specified string data using a `Value` field appropriate to
520 // `str_type`.  Truncates `str` if necessary, but emits nothing and marks the
521 // buffer full if  even the field headers do not fit.
CopyToEncodedBuffer(absl::string_view str,StringType str_type)522 void LogMessage::CopyToEncodedBuffer(absl::string_view str,
523                                      StringType str_type) {
524   auto encoded_remaining_copy = data_->encoded_remaining;
525   auto start = EncodeMessageStart(
526       EventTag::kValue, BufferSizeFor(WireType::kLengthDelimited) + str.size(),
527       &encoded_remaining_copy);
528   // If the `logging.proto.Event.value` field header did not fit,
529   // `EncodeMessageStart` will have zeroed `encoded_remaining_copy`'s size and
530   // `EncodeStringTruncate` will fail too.
531   if (EncodeStringTruncate(str_type == StringType::kLiteral
532                                ? ValueTag::kStringLiteral
533                                : ValueTag::kString,
534                            str, &encoded_remaining_copy)) {
535     // The string may have been truncated, but the field header fit.
536     EncodeMessageLength(start, &encoded_remaining_copy);
537     data_->encoded_remaining = encoded_remaining_copy;
538   } else {
539     // The field header(s) did not fit; zero `encoded_remaining` so we don't
540     // write anything else later.
541     data_->encoded_remaining.remove_suffix(data_->encoded_remaining.size());
542   }
543 }
CopyToEncodedBuffer(char ch,size_t num,StringType str_type)544 void LogMessage::CopyToEncodedBuffer(char ch, size_t num, StringType str_type) {
545   auto encoded_remaining_copy = data_->encoded_remaining;
546   auto value_start = EncodeMessageStart(
547       EventTag::kValue, BufferSizeFor(WireType::kLengthDelimited) + num,
548       &encoded_remaining_copy);
549   auto str_start = EncodeMessageStart(str_type == StringType::kLiteral
550                                           ? ValueTag::kStringLiteral
551                                           : ValueTag::kString,
552                                       num, &encoded_remaining_copy);
553   if (str_start.data()) {
554     // The field headers fit.
555     log_internal::AppendTruncated(ch, num, encoded_remaining_copy);
556     EncodeMessageLength(str_start, &encoded_remaining_copy);
557     EncodeMessageLength(value_start, &encoded_remaining_copy);
558     data_->encoded_remaining = encoded_remaining_copy;
559   } else {
560     // The field header(s) did not fit; zero `encoded_remaining` so we don't
561     // write anything else later.
562     data_->encoded_remaining.remove_suffix(data_->encoded_remaining.size());
563   }
564 }
565 
LogMessageFatal(const char * file,int line)566 LogMessageFatal::LogMessageFatal(const char* file, int line)
567     : LogMessage(file, line, absl::LogSeverity::kFatal) {}
568 
LogMessageFatal(const char * file,int line,absl::string_view failure_msg)569 LogMessageFatal::LogMessageFatal(const char* file, int line,
570                                  absl::string_view failure_msg)
571     : LogMessage(file, line, absl::LogSeverity::kFatal) {
572   *this << "Check failed: " << failure_msg << " ";
573 }
574 
575 // ABSL_ATTRIBUTE_NORETURN doesn't seem to work on destructors with msvc, so
576 // disable msvc's warning about the d'tor never returning.
577 #if defined(_MSC_VER) && !defined(__clang__)
578 #pragma warning(push)
579 #pragma warning(disable : 4722)
580 #endif
~LogMessageFatal()581 LogMessageFatal::~LogMessageFatal() {
582   Flush();
583   FailWithoutStackTrace();
584 }
585 #if defined(_MSC_VER) && !defined(__clang__)
586 #pragma warning(pop)
587 #endif
588 
LogMessageQuietlyFatal(const char * file,int line)589 LogMessageQuietlyFatal::LogMessageQuietlyFatal(const char* file, int line)
590     : LogMessage(file, line, absl::LogSeverity::kFatal) {
591   SetFailQuietly();
592 }
593 
LogMessageQuietlyFatal(const char * file,int line,absl::string_view failure_msg)594 LogMessageQuietlyFatal::LogMessageQuietlyFatal(const char* file, int line,
595                                                absl::string_view failure_msg)
596     : LogMessage(file, line, absl::LogSeverity::kFatal) {
597   SetFailQuietly();
598   *this << "Check failed: " << failure_msg << " ";
599 }
600 
601 // ABSL_ATTRIBUTE_NORETURN doesn't seem to work on destructors with msvc, so
602 // disable msvc's warning about the d'tor never returning.
603 #if defined(_MSC_VER) && !defined(__clang__)
604 #pragma warning(push)
605 #pragma warning(disable : 4722)
606 #endif
~LogMessageQuietlyFatal()607 LogMessageQuietlyFatal::~LogMessageQuietlyFatal() {
608   Flush();
609   FailQuietly();
610 }
611 #if defined(_MSC_VER) && !defined(__clang__)
612 #pragma warning(pop)
613 #endif
614 
615 }  // namespace log_internal
616 
617 ABSL_NAMESPACE_END
618 }  // namespace absl
619