Skip to content

Fix poisoning leftover for vector and string ASan annotations#6285

Open
amyw-msft wants to merge 4 commits into
microsoft:mainfrom
amyw-msft:asan_leftover_poisoning
Open

Fix poisoning leftover for vector and string ASan annotations#6285
amyw-msft wants to merge 4 commits into
microsoft:mainfrom
amyw-msft:asan_leftover_poisoning

Conversation

@amyw-msft
Copy link
Copy Markdown
Member

Fixes #6276

AddressSanitizer poisons memory in 8 byte chunks. It can mark a memory region as 'partially addressable', but only by marking the first x bytes as valid to access and remaining as poisoned. There is no way to say "only the first x bytes are poisoned". The result is that the ends of buffers that are not 8-byte aligned either need to over-poison past the end of the buffer, or under-poison and allow potential buffer overflow to go unnoticed under ASan.

For ASan container annotations, we choose which strategy to use based on the allocator. If we can be sure that the allocator only allocations in 8-byte aligned chunks, then we can safely over-poison past the end of the buffer. However, when we do this (increase the pointer that points to the 'end'), we also need to adjust the actual 'last valid' pointer as well if they are equal, because the way we clean up the container poisoning is by calling that annotations API, saying that the last valid and the end pointer are the same.

This change checks for this condition and advances the 'last valid' pointer if it is equal to the 'end' pointer. Without this fix, shadow bytes will remain poisoned after an annotated container leaves scope.

…'end' point in situations where the end has been extended to the end of the allocation block.
Copilot AI review requested due to automatic review settings May 13, 2026 23:35
@amyw-msft amyw-msft requested a review from a team as a code owner May 13, 2026 23:35
@github-project-automation github-project-automation Bot moved this to Initial Review in STL Code Reviews May 13, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes ASan container annotation cleanup for std::vector and std::basic_string when the allocator is at least 8-byte aligned. In that path, the implementation over-poisons up to the next 8-byte shadow boundary past _End. When removing or shrinking the annotation, the "old/new last valid" pointers passed to __sanitizer_annotate_contiguous_container must also be bumped to that same aligned boundary whenever they equal _End; otherwise the trailing shadow bytes past _End remain poisoned after the container goes out of scope.

Changes:

  • In stl/inc/vector's aligned-allocator branch of _Apply_annotation, advance _Old_last/_New_last to the aligned-after-end pointer when they equal _End.
  • Apply the analogous fix to stl/inc/xstring's _Apply_annotation, and restructure the function so the aligned branch returns early.
  • Add a new regression test (GH_006276_annotation_poison_cleanup) exercising both the under-poison and over-poison paths for string and vector with an ASan-unaware arena allocator.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
stl/inc/vector Compute aligned old/new last pointers and pass them to the sanitizer call in the aligned-allocator branch.
stl/inc/xstring Same fix for basic_string; restructure so the aligned branch returns early before the non-aligned code.
tests/std/tests/GH_006276_annotation_poison_cleanup/test.cpp New regression test verifying shadow bytes are fully cleared after container destruction.
tests/std/tests/GH_006276_annotation_poison_cleanup/env.lst ASan test matrix for the new test.
tests/std/test.lst Register the new test directory.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread stl/inc/xstring
Copilot AI review requested due to automatic review settings May 14, 2026 17:13
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Copy link
Copy Markdown
Member

@davidmrdavid davidmrdavid left a comment

Choose a reason for hiding this comment

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

LGTM, but will defer to STL. Just a small observation

Comment thread tests/std/tests/GH_006276_annotation_poison_cleanup/test.cpp
@StephanTLavavej
Copy link
Copy Markdown
Member

ARM64 crash in the new test; is this something concerning, or pre-existing rare flakiness?

Test step failed unexpectedly.
Command: "C:\stlBuild\tests\std\tests\GH_006276_annotation_poison_cleanup\Output\15\GH_006276_annotation_poison_cleanup.exe"
Exit Code: 3221225477 (0xC0000005)

@StephanTLavavej StephanTLavavej added bug Something isn't working ASan Address Sanitizer labels May 14, 2026
@StephanTLavavej StephanTLavavej moved this from Initial Review to Work In Progress in STL Code Reviews May 14, 2026
Copy link
Copy Markdown
Member

@zacklj89 zacklj89 left a comment

Choose a reason for hiding this comment

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

I don't immediately know what could be causing the ARM64 failure, but let me know if I can help investigate.

Comment thread stl/inc/vector
const void* const _Old_last = _STD _Unfancy(_Old_last_);
const void* const _New_last = _STD _Unfancy(_New_last_);
if constexpr ((_Container_allocation_minimum_asan_alignment<vector>) >= _Asan_granularity) {
// If we realign the _End forward to maximize coverage, we need to keep other significant points
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

By "significant points" here, we mean _Old_last and _New_last right? Maybe we could clarify if there's another push:

// If we realign _End forward to maximize coverage, also realign _Old_last and _New_last when they
// equal _End. Otherwise, the ASan annotation may leave stale shadow bytes behind when cleaning up.

Comment thread stl/inc/vector

// Allocation is potentially unaligned, so we cannot annotate whole buffer since we might be
// entering memory owned by someone else. Therefore, pull back where the annotations end on the buffer,
// but may miss some coverage near end of buffer.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Another comment comment, but feel free to not integrate it. I haven't worked as closely here as you, so maybe this is redundant, but:

// The allocation may not end on an ASan granularity boundary. In that case, annotating up to _End
// could affect shadow bytes for memory beyond this allocation, so restrict annotations to the largest
// aligned subrange inside the buffer. This may leave the tail of the buffer unannotated.

Comment thread stl/inc/xstring

const void* const _New_end_aligned = _STD _Get_asan_aligned_after(_End);
const void* const _Old_last_aligned = (_Old_last == _End) ? _New_end_aligned : _Old_last;
const void* const _New_last_aligned = (_New_last == _End) ? _New_end_aligned : _New_last;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nice work 🥲

test_arena.print_shadow();
}

int main() {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do you think it would be worthwhile to add a test here that does like shrink from full and tests the shadow, like testing _Old_last == _End and doing pop_back() on a full vector/string?

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

Labels

ASan Address Sanitizer bug Something isn't working

Projects

Status: Work In Progress

Development

Successfully merging this pull request may close these issues.

ASan STL string and vector annotations leave poisoning behind

5 participants