Skip to content

Conversation

@ozguronsoy
Copy link

When optional is empty the internal storage is poisoned, it's unpoisoned when a value is assigned.

  • Added _ANNOTATE_OPTIONAL, _DISABLE_OPTIONAL_ANNOTATION, etc. to __msvc_sanitizer_annotate_container.hpp.
  • Added poisoning storage in _Optional_destruct_base on empty construction and reset.
  • Added unpoisoning of storage in _Optional_construct_base::_Construct.
  • Added poisoning and unpoisoning tests.

Resolves #5974

@ozguronsoy ozguronsoy requested a review from a team as a code owner January 14, 2026 00:23
@github-project-automation github-project-automation bot moved this to Initial Review in STL Code Reviews Jan 14, 2026
@ozguronsoy
Copy link
Author

@microsoft-github-policy-service agree

@StephanTLavavej StephanTLavavej changed the title Add address sanitizer annotations to optional <optional>: Add Address Sanitizer annotations Jan 14, 2026
@StephanTLavavej StephanTLavavej added enhancement Something can be improved ASan Address Sanitizer labels Jan 14, 2026
@StephanTLavavej
Copy link
Member

Thank you! I need to focus on landing <flat_map> and <flat_set>, but I'll review this when I get a chance.

#endif

#ifdef _INSERT_OPTIONAL_ANNOTATION
extern const bool _Asan_optional_should_annotate;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This variable isn't used. Is it really necessary?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a check for this variable inside the if(!_STD _Is_constant_evaluated()) block.

#endif
} // extern "C"

#if defined(_INSERT_VECTOR_ANNOTATION) || defined(_INSERT_STRING_ANNOTATION)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there should be a concentrated controlling macro for these.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's necessary since this check is only done here. I also added defined(_INSERT_OPTIONAL_ANNOTATION) to the check.

stl/inc/optional Outdated
constexpr _Optional_destruct_base() noexcept : _Dummy{}, _Has_value{false} {} // initialize an empty optional
constexpr _Optional_destruct_base() noexcept : _Dummy{}, _Has_value{false} {
#ifdef _INSERT_OPTIONAL_ANNOTATION
__asan_poison_memory_region(_STD addressof(_Value), sizeof(_Value));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This invocations probably break constant evaluation. We should wrap them in if (!_STD _Is_constant_evaluated()) { }, IMO.

Also, why not consistently write sizeof(_Ty)?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Also, why not consistently write sizeof(_Ty)?

That's how I usually write it. Changed it to sizeof(_Ty) to match the existing style.


void test_emplace_unpoisoning() {
std::optional<Payload> opt;
opt.emplace(Payload());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For clarity:

Suggested change
opt.emplace(Payload());
opt.emplace();

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


void test_assignment_unpoisoning() {
std::optional<Payload> opt = std::nullopt;
opt = Payload();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For clarity, to avoid confusion with type-id:

Suggested change
opt = Payload();
opt = Payload{};

Ditto below.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Comment on lines +49 to +52
test_poison_on_empty_access();
test_emplace_unpoisoning();
test_assignment_unpoisoning();
test_repoison_after_reset();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can make these cases constexpr-friendly and test them in static_assert since C++20.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a separate function to test constexpr functionality in static_assert.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ASan Address Sanitizer enhancement Something can be improved

Projects

Status: Initial Review

Development

Successfully merging this pull request may close these issues.

<optional>: address sanitizer annotation

3 participants