Skip to content

Commit d750c6d

Browse files
authored
[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.
1 parent 78faf99 commit d750c6d

File tree

9 files changed

+110
-0
lines changed

9 files changed

+110
-0
lines changed

libcxx/include/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,7 @@ set(files
535535
__locale_dir/time.h
536536
__locale_dir/wbuffer_convert.h
537537
__locale_dir/wstring_convert.h
538+
__log_hardening_failure
538539
__math/abs.h
539540
__math/copysign.h
540541
__math/error_functions.h

libcxx/include/__config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ _LIBCPP_HARDENING_MODE_DEBUG
207207
# define _LIBCPP_HAS_EXPERIMENTAL_PSTL _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
208208
# define _LIBCPP_HAS_EXPERIMENTAL_TZDB _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
209209
# define _LIBCPP_HAS_EXPERIMENTAL_SYNCSTREAM _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
210+
# define _LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
210211

211212
# if defined(__MVS__)
212213
# include <features.h> // for __NATIVE_ASCII_F
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// -*- C++ -*-
2+
//===----------------------------------------------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#ifndef _LIBCPP___LOG_HARDENING_FAILURE
11+
#define _LIBCPP___LOG_HARDENING_FAILURE
12+
13+
#include <__config>
14+
15+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
16+
# pragma GCC system_header
17+
#endif
18+
19+
// Hardening logging is not available in the C++03 mode; moreover, it is currently only available in the experimental
20+
// library.
21+
#if _LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC && !defined(_LIBCPP_CXX03_LANG)
22+
23+
_LIBCPP_BEGIN_NAMESPACE_STD
24+
25+
// This function should never be called directly from the code -- it should only be called through the
26+
// `_LIBCPP_LOG_HARDENING_FAILURE` macro.
27+
[[__gnu__::__cold__]] _LIBCPP_EXPORTED_FROM_ABI void __log_hardening_failure(const char* __message) noexcept;
28+
29+
// _LIBCPP_LOG_HARDENING_FAILURE(message)
30+
//
31+
// This macro is used to log an error without terminating the program (as is the case for hardening failures if the
32+
// `observe` assertion semantic is used).
33+
34+
# if !defined(_LIBCPP_LOG_HARDENING_FAILURE)
35+
# define _LIBCPP_LOG_HARDENING_FAILURE(__message) ::std::__log_hardening_failure(__message)
36+
# endif // !defined(_LIBCPP_LOG_HARDENING_FAILURE)
37+
38+
_LIBCPP_END_NAMESPACE_STD
39+
40+
#endif // _LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC && !defined(_LIBCPP_CXX03_LANG)
41+
42+
#endif // _LIBCPP___LOG_HARDENING_FAILURE

libcxx/include/module.modulemap.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2355,6 +2355,9 @@ module std [system] {
23552355
header "__std_mbstate_t.h"
23562356
export *
23572357
}
2358+
module log_hardening_failure {
2359+
header "__log_hardening_failure"
2360+
}
23582361
module verbose_abort {
23592362
header "__verbose_abort"
23602363
}

libcxx/src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ add_custom_target(cxx DEPENDS ${LIBCXX_BUILD_TARGETS})
309309
# Build the experimental static library
310310
set(LIBCXX_EXPERIMENTAL_SOURCES
311311
experimental/keep.cpp
312+
experimental/log_hardening_failure.cpp
312313
)
313314

314315
if (LIBCXX_PSTL_BACKEND STREQUAL "libdispatch")
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include <__config>
10+
#include <__log_hardening_failure>
11+
#include <cstdio>
12+
13+
#ifdef __BIONIC__
14+
# include <syslog.h>
15+
#endif // __BIONIC__
16+
17+
_LIBCPP_BEGIN_NAMESPACE_STD
18+
19+
void __log_hardening_failure(const char* message) noexcept {
20+
// Always log the message to `stderr` in case the platform-specific system calls fail.
21+
std::fputs(message, stderr);
22+
23+
#if defined(__BIONIC__)
24+
// Show error in logcat. The latter two arguments are ignored on Android.
25+
openlog("libc++", 0, 0);
26+
syslog(LOG_CRIT, "%s", message);
27+
closelog();
28+
#endif
29+
}
30+
31+
_LIBCPP_END_NAMESPACE_STD
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// Basic smoke test for `__log_hardening_failure`.
10+
//
11+
// UNSUPPORTED: c++03
12+
// UNSUPPORTED: libcpp-has-no-experimental-hardening-observe-semantic
13+
14+
#include <__log_hardening_failure>
15+
16+
#include "test_macros.h"
17+
18+
ASSERT_NOEXCEPT(std::__log_hardening_failure(""));
19+
20+
int main(int, char**) {
21+
std::__log_hardening_failure("Some message");
22+
// It's difficult to properly test platform-specific logging behavior of the function; just make sure it exists and
23+
// can be called at runtime.
24+
25+
return 0;
26+
}

libcxx/test/libcxx/experimental/fexperimental-library.compile.pass.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,7 @@
2929
#if !_LIBCPP_HAS_EXPERIMENTAL_SYNCSTREAM
3030
# error "-fexperimental-library should enable the syncstream header"
3131
#endif
32+
33+
#if !_LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC
34+
# error "-fexperimental-library should allow using the Hardening observe semantic"
35+
#endif

libcxx/utils/libcxx/test/params.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,7 @@ def getSuitableClangTidy(cfg):
361361
AddFeature("libcpp-has-no-incomplete-pstl"),
362362
AddFeature("libcpp-has-no-experimental-tzdb"),
363363
AddFeature("libcpp-has-no-experimental-syncstream"),
364+
AddFeature("libcpp-has-no-experimental-hardening-observe-semantic"),
364365
],
365366
),
366367
# TODO: This can be improved once we use a version of GoogleBenchmark that supports the dry-run mode.

0 commit comments

Comments
 (0)