Skip to content

Commit 70c8126

Browse files
Hardened 'basic_stacktrace::current' (p3697r0)
1 parent 1f0bbc9 commit 70c8126

File tree

2 files changed

+41
-2
lines changed

2 files changed

+41
-2
lines changed

libcxx/include/__stacktrace/basic.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#ifndef _LIBCPP_STACKTRACE_BASIC
1111
#define _LIBCPP_STACKTRACE_BASIC
1212

13+
#include "__assert"
1314
#include <__config>
1415

1516
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -81,20 +82,27 @@ class _LIBCPP_EXPORTED_FROM_ABI basic_stacktrace : private __stacktrace::base {
8182
// (19.6.4.2)
8283
// Creation and assignment [stacktrace.basic.cons]
8384

85+
// Should be generous, but not so large that it would easily lead to an overflow
86+
// when added to a given skip amount.
87+
constexpr static size_type __default_max_depth = 1024;
88+
8489
_LIBCPP_NO_TAIL_CALLS _LIBCPP_NOINLINE _LIBCPP_EXPORTED_FROM_ABI static basic_stacktrace
8590
current(const allocator_type& __caller_alloc = allocator_type()) noexcept(__kNoThrowAlloc) {
86-
return current(1, /* no __max_depth */ ~0, __caller_alloc);
91+
return current(1, __default_max_depth, __caller_alloc);
8792
}
8893

8994
_LIBCPP_NO_TAIL_CALLS _LIBCPP_NOINLINE _LIBCPP_EXPORTED_FROM_ABI static basic_stacktrace
9095
current(size_type __skip, const allocator_type& __caller_alloc = allocator_type()) noexcept(__kNoThrowAlloc) {
91-
return current(__skip + 1, /* no __max_depth */ ~0, __caller_alloc);
96+
return current(__skip + 1, __default_max_depth, __caller_alloc);
9297
}
9398

9499
_LIBCPP_NO_TAIL_CALLS _LIBCPP_NOINLINE _LIBCPP_EXPORTED_FROM_ABI static basic_stacktrace
95100
current(size_type __skip,
96101
size_type __max_depth,
97102
const allocator_type& __caller_alloc = allocator_type()) noexcept(__kNoThrowAlloc) {
103+
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
104+
__skip <= __skip + __max_depth, "sum of skip and max_depth too large; overflows size_type");
105+
98106
__stacktrace::base __builder(__caller_alloc);
99107
__builder.build_stacktrace(__skip + 1, __max_depth);
100108
basic_stacktrace<_Allocator> __ret{__caller_alloc};
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+
// REQUIRES: std-at-least-c++23, has-unix-headers, libcpp-hardening-mode={{extensive|debug}}
10+
// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
11+
12+
/*
13+
Hardened requirements for the `current` call with given `skip` and `max_depth` amounts:
14+
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3697r0.html#basic_stacktrace
15+
Specifically: "Hardened preconditions: skip <= skip + max_depth is true."
16+
17+
// (19.6.4.2): [stacktrace.basic.cons], creation and assignment
18+
static basic_stacktrace current(size_type skip, size_type max_depth,
19+
const allocator_type& alloc = allocator_type()) noexcept;
20+
*/
21+
22+
#include <stacktrace>
23+
24+
#include "check_assertion.h"
25+
26+
int main(int, char**) {
27+
TEST_LIBCPP_ASSERT_FAILURE(
28+
std::stacktrace::current(1, 0xffffffffffffffff), "sum of skip and max_depth too large; overflows size_type");
29+
30+
return 0;
31+
}

0 commit comments

Comments
 (0)