-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[libc++][hardening] Categorize more assertions. #75918
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b1680c8
9a8622d
bcc8ef2
cd4d8c7
904bb3e
24d8122
cc436df
2d66073
8405233
ea26d9d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -73,7 +73,8 @@ class directory_iterator { | |
_LIBCPP_HIDE_FROM_ABI ~directory_iterator() = default; | ||
|
||
_LIBCPP_HIDE_FROM_ABI const directory_entry& operator*() const { | ||
_LIBCPP_ASSERT_UNCATEGORIZED(__imp_, "The end iterator cannot be dereferenced"); | ||
// Note: this check duplicates a check in `__dereference()`. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Per our discussion just now, these are the different ways we can think of handling the situation of "redundant" checks: // Option #1: leave it as-is
void f(std::optional<T> foo) {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(foo.has_value(), "oops");
use(*foo);
}
// Option #2: remove it, it's implicitly checked, we "know" it
void f(std::optional<T> foo) {
use(*foo);
}
// Option #3: Use a comment
void f(std::optional<T> foo) {
// implicit precondition: foo.has_value(), already checked in operator* below
use(*foo);
}
// Option #4: Macro orthogonal to the assertion category
void f(std::optional<T> foo) {
_LIBCPP_REDUNDANT_ASSERTION(_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(foo.has_value(), "oops"));
use(*foo);
}
// Option #5: Add a new category
void f(std::optional<T> foo) {
// REDUNDANT|EARLY|EXTRA|...
_LIBCPP_ASSERT_EARLY(foo.has_value(), "oops");
use(*foo);
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Discussion just now, we discussed this by elimination:
It seems we have a preference for |
||
_LIBCPP_ASSERT_NON_NULL(__imp_, "The end iterator cannot be dereferenced"); | ||
return __dereference(); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -115,7 +115,7 @@ class _LIBCPP_TEMPLATE_VIS __output_buffer { | |
|
||
// The output doesn't fit in the internal buffer. | ||
// Copy the data in "__capacity_" sized chunks. | ||
_LIBCPP_ASSERT_UNCATEGORIZED(__size_ == 0, "the buffer should be flushed by __flush_on_overflow"); | ||
_LIBCPP_ASSERT_INTERNAL(__size_ == 0, "the buffer should be flushed by __flush_on_overflow"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mordante If you have the time, it would be great if you could see if the classification in |
||
const _InCharT* __first = __str.data(); | ||
do { | ||
size_t __chunk = std::min(__n, __capacity_); | ||
|
@@ -134,7 +134,7 @@ class _LIBCPP_TEMPLATE_VIS __output_buffer { | |
class _UnaryOperation, | ||
__fmt_char_type _InCharT = typename iterator_traits<_Iterator>::value_type> | ||
_LIBCPP_HIDE_FROM_ABI void __transform(_Iterator __first, _Iterator __last, _UnaryOperation __operation) { | ||
_LIBCPP_ASSERT_UNCATEGORIZED(__first <= __last, "not a valid range"); | ||
_LIBCPP_ASSERT_INTERNAL(__first <= __last, "not a valid range"); | ||
|
||
size_t __n = static_cast<size_t>(__last - __first); | ||
__flush_on_overflow(__n); | ||
|
@@ -146,7 +146,7 @@ class _LIBCPP_TEMPLATE_VIS __output_buffer { | |
|
||
// The output doesn't fit in the internal buffer. | ||
// Transform the data in "__capacity_" sized chunks. | ||
_LIBCPP_ASSERT_UNCATEGORIZED(__size_ == 0, "the buffer should be flushed by __flush_on_overflow"); | ||
_LIBCPP_ASSERT_INTERNAL(__size_ == 0, "the buffer should be flushed by __flush_on_overflow"); | ||
do { | ||
size_t __chunk = std::min(__n, __capacity_); | ||
std::transform(__first, __first + __chunk, std::addressof(__ptr_[__size_]), __operation); | ||
|
@@ -168,7 +168,7 @@ class _LIBCPP_TEMPLATE_VIS __output_buffer { | |
|
||
// The output doesn't fit in the internal buffer. | ||
// Fill the buffer in "__capacity_" sized chunks. | ||
_LIBCPP_ASSERT_UNCATEGORIZED(__size_ == 0, "the buffer should be flushed by __flush_on_overflow"); | ||
_LIBCPP_ASSERT_INTERNAL(__size_ == 0, "the buffer should be flushed by __flush_on_overflow"); | ||
do { | ||
size_t __chunk = std::min(__n, __capacity_); | ||
std::fill_n(std::addressof(__ptr_[__size_]), __chunk, __value); | ||
|
@@ -596,7 +596,7 @@ class _LIBCPP_TEMPLATE_VIS __retarget_buffer { | |
class _UnaryOperation, | ||
__fmt_char_type _InCharT = typename iterator_traits<_Iterator>::value_type> | ||
_LIBCPP_HIDE_FROM_ABI void __transform(_Iterator __first, _Iterator __last, _UnaryOperation __operation) { | ||
_LIBCPP_ASSERT_UNCATEGORIZED(__first <= __last, "not a valid range"); | ||
_LIBCPP_ASSERT_INTERNAL(__first <= __last, "not a valid range"); | ||
|
||
size_t __n = static_cast<size_t>(__last - __first); | ||
if (__size_ + __n >= __capacity_) | ||
|
@@ -623,7 +623,7 @@ class _LIBCPP_TEMPLATE_VIS __retarget_buffer { | |
_LIBCPP_HIDE_FROM_ABI void __grow_buffer() { __grow_buffer(__capacity_ * 1.6); } | ||
|
||
_LIBCPP_HIDE_FROM_ABI void __grow_buffer(size_t __capacity) { | ||
_LIBCPP_ASSERT_UNCATEGORIZED(__capacity > __capacity_, "the buffer must grow"); | ||
_LIBCPP_ASSERT_INTERNAL(__capacity > __capacity_, "the buffer must grow"); | ||
auto __result = std::__allocate_at_least(__alloc_, __capacity); | ||
auto __guard = std::__make_exception_guard([&] { | ||
allocator_traits<_Alloc>::deallocate(__alloc_, __result.ptr, __result.count); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would consider taking advantage of this precondition and removing
if (__len > 1)
, but then bumping this assertion to a valid-range (or similar) assertion. Thoughts? If we opt to do this, it would be as a separate change.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea, but would prefer to do this in a separate PR and merge after the next release is branched.