Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 830cf804 authored by Henri Chataing's avatar Henri Chataing
Browse files

system/log: Add protection against nullptr string parameters

As opposed to printf("%s", nullptr); log::info("{}", nullptr) will
cause a segfault at runtime. This change adds swaps nullptr
string parameters in the code and replaces them with the
"(nullptr)" string.

Bug: 305066880
Test: atest libbluetooth_log_test
Flag: EXEMPT, log change
Change-Id: I9acbcc4dac2c2b12b2ff888805738a088513d45a
parent 7f32aabe
Loading
Loading
Loading
Loading
+25 −1
Original line number Diff line number Diff line
@@ -44,13 +44,37 @@ void vlog(Level level, char const* tag, char const* file_name, int line,
          char const* function_name, fmt::string_view fmt,
          fmt::format_args vargs);

/// Capture invalid parameter values that would cause runtime
/// formatting errors.
template <class T>
[[maybe_unused]] static inline T& format_replace(T& arg) {
  return arg;
}

/// Specialization of format_replace for nullptr string parameters.
template <>
char const*& format_replace(char const*& arg) {
  static char const* nullptr_str = "(nullptr)";
  if (arg) return arg;
  return nullptr_str;
}

/// Specialization of format_replace for nullptr string parameters.
template <>
char*& format_replace(char*& arg) {
  static char* nullptr_str = (char*)"(nullptr)";
  if (arg) return arg;
  return nullptr_str;
}

template <Level level, typename... T>
struct log {
  log(fmt::format_string<T...> fmt, T&&... args,
      char const* file_name = __builtin_FILE(), int line = __builtin_LINE(),
      char const* function_name = __builtin_FUNCTION()) {
    vlog(level, LOG_TAG, file_name, line, function_name,
         static_cast<fmt::string_view>(fmt), fmt::make_format_args(args...));
         static_cast<fmt::string_view>(fmt),
         fmt::make_format_args(format_replace(args)...));
  }
};

+20 −0
Original line number Diff line number Diff line
@@ -112,3 +112,23 @@ TEST(BluetoothLoggerTest, error) {
  EXPECT_EQ(androidLogMessage->line, 105);
  EXPECT_STREQ(androidLogMessage->message, "TestBody: error test");
}

TEST(BluetoothLoggerTest, null_string_parameter) {
  androidLogMessage.reset();

  char const* const_null_str = nullptr;
  log::info("input: {}", const_null_str);
  EXPECT_STREQ(androidLogMessage->message, "TestBody: input: (nullptr)");

  androidLogMessage.reset();

  char* null_str = nullptr;
  log::info("input: {}", null_str);
  EXPECT_STREQ(androidLogMessage->message, "TestBody: input: (nullptr)");

  androidLogMessage.reset();

  char const* nonnull_str = "hello world";
  log::info("input: {}", nonnull_str);
  EXPECT_STREQ(androidLogMessage->message, "TestBody: input: hello world");
}