[libc++][hardening] Add an experimental function to log hardening errors (#149452)
Unlike `verbose_abort`, this function merely logs the error but does not terminate execution. It is intended to make it possible to implement the `observe` semantic for Hardening. (cherry picked from commit d750c6de8a75cbe2bc16c136764195471be8f0b7)
This commit is contained in:
parent
1ddf4e3887
commit
ee86ae0a69
@ -535,6 +535,7 @@ set(files
|
||||
__locale_dir/time.h
|
||||
__locale_dir/wbuffer_convert.h
|
||||
__locale_dir/wstring_convert.h
|
||||
__log_hardening_failure
|
||||
__math/abs.h
|
||||
__math/copysign.h
|
||||
__math/error_functions.h
|
||||
|
@ -207,6 +207,7 @@ _LIBCPP_HARDENING_MODE_DEBUG
|
||||
# define _LIBCPP_HAS_EXPERIMENTAL_PSTL _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
|
||||
# define _LIBCPP_HAS_EXPERIMENTAL_TZDB _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
|
||||
# define _LIBCPP_HAS_EXPERIMENTAL_SYNCSTREAM _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
|
||||
# define _LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
|
||||
|
||||
# if defined(__MVS__)
|
||||
# include <features.h> // for __NATIVE_ASCII_F
|
||||
|
42
libcxx/include/__log_hardening_failure
Normal file
42
libcxx/include/__log_hardening_failure
Normal file
@ -0,0 +1,42 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___LOG_HARDENING_FAILURE
|
||||
#define _LIBCPP___LOG_HARDENING_FAILURE
|
||||
|
||||
#include <__config>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
// Hardening logging is not available in the C++03 mode; moreover, it is currently only available in the experimental
|
||||
// library.
|
||||
#if _LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC && !defined(_LIBCPP_CXX03_LANG)
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
// This function should never be called directly from the code -- it should only be called through the
|
||||
// `_LIBCPP_LOG_HARDENING_FAILURE` macro.
|
||||
[[__gnu__::__cold__]] _LIBCPP_EXPORTED_FROM_ABI void __log_hardening_failure(const char* __message) noexcept;
|
||||
|
||||
// _LIBCPP_LOG_HARDENING_FAILURE(message)
|
||||
//
|
||||
// This macro is used to log an error without terminating the program (as is the case for hardening failures if the
|
||||
// `observe` assertion semantic is used).
|
||||
|
||||
# if !defined(_LIBCPP_LOG_HARDENING_FAILURE)
|
||||
# define _LIBCPP_LOG_HARDENING_FAILURE(__message) ::std::__log_hardening_failure(__message)
|
||||
# endif // !defined(_LIBCPP_LOG_HARDENING_FAILURE)
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC && !defined(_LIBCPP_CXX03_LANG)
|
||||
|
||||
#endif // _LIBCPP___LOG_HARDENING_FAILURE
|
@ -2353,6 +2353,9 @@ module std [system] {
|
||||
header "__std_mbstate_t.h"
|
||||
export *
|
||||
}
|
||||
module log_hardening_failure {
|
||||
header "__log_hardening_failure"
|
||||
}
|
||||
module verbose_abort {
|
||||
header "__verbose_abort"
|
||||
}
|
||||
|
@ -309,6 +309,7 @@ add_custom_target(cxx DEPENDS ${LIBCXX_BUILD_TARGETS})
|
||||
# Build the experimental static library
|
||||
set(LIBCXX_EXPERIMENTAL_SOURCES
|
||||
experimental/keep.cpp
|
||||
experimental/log_hardening_failure.cpp
|
||||
)
|
||||
|
||||
if (LIBCXX_PSTL_BACKEND STREQUAL "libdispatch")
|
||||
|
31
libcxx/src/experimental/log_hardening_failure.cpp
Normal file
31
libcxx/src/experimental/log_hardening_failure.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <__config>
|
||||
#include <__log_hardening_failure>
|
||||
#include <cstdio>
|
||||
|
||||
#ifdef __BIONIC__
|
||||
# include <syslog.h>
|
||||
#endif // __BIONIC__
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
void __log_hardening_failure(const char* message) noexcept {
|
||||
// Always log the message to `stderr` in case the platform-specific system calls fail.
|
||||
std::fputs(message, stderr);
|
||||
|
||||
#if defined(__BIONIC__)
|
||||
// Show error in logcat. The latter two arguments are ignored on Android.
|
||||
openlog("libc++", 0, 0);
|
||||
syslog(LOG_CRIT, "%s", message);
|
||||
closelog();
|
||||
#endif
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
26
libcxx/test/libcxx/assertions/log_hardening_failure.pass.cpp
Normal file
26
libcxx/test/libcxx/assertions/log_hardening_failure.pass.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Basic smoke test for `__log_hardening_failure`.
|
||||
//
|
||||
// UNSUPPORTED: c++03
|
||||
// UNSUPPORTED: libcpp-has-no-experimental-hardening-observe-semantic
|
||||
|
||||
#include <__log_hardening_failure>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
ASSERT_NOEXCEPT(std::__log_hardening_failure(""));
|
||||
|
||||
int main(int, char**) {
|
||||
std::__log_hardening_failure("Some message");
|
||||
// It's difficult to properly test platform-specific logging behavior of the function; just make sure it exists and
|
||||
// can be called at runtime.
|
||||
|
||||
return 0;
|
||||
}
|
@ -29,3 +29,7 @@
|
||||
#if !_LIBCPP_HAS_EXPERIMENTAL_SYNCSTREAM
|
||||
# error "-fexperimental-library should enable the syncstream header"
|
||||
#endif
|
||||
|
||||
#if !_LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC
|
||||
# error "-fexperimental-library should allow using the Hardening observe semantic"
|
||||
#endif
|
||||
|
@ -361,6 +361,7 @@ DEFAULT_PARAMETERS = [
|
||||
AddFeature("libcpp-has-no-incomplete-pstl"),
|
||||
AddFeature("libcpp-has-no-experimental-tzdb"),
|
||||
AddFeature("libcpp-has-no-experimental-syncstream"),
|
||||
AddFeature("libcpp-has-no-experimental-hardening-observe-semantic"),
|
||||
],
|
||||
),
|
||||
# TODO: This can be improved once we use a version of GoogleBenchmark that supports the dry-run mode.
|
||||
|
Loading…
x
Reference in New Issue
Block a user