-
Notifications
You must be signed in to change notification settings - Fork 11.8k
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
Container annotations (-fstanitize=address) crash when used with sizeof(*buffer) < shadow granularity #53538
Comments
Hey, thank you for the example! It looks like /// \param beg Beginning of memory region.
/// \param end End of memory region.
/// \param old_mid Old middle of memory region.
/// \param new_mid New middle of memory region.
void __sanitizer_annotate_contiguous_container(const void *beg,
const void *end,
const void *old_mid,
const void *new_mid); The Explanation of the issue: if (buffer) {
__sanitizer_annotate_contiguous_container(buffer, buffer + capacity, buffer + capacity, buffer + capacity);
// ^ That's correct, but does not change anything, at the beginning the whole buffer is accessible
__sanitizer_annotate_contiguous_container(buffer, buffer + capacity, buffer + capacity, buffer + 0);
// ^ That's correct, `old_mid == buffer + capacity`, the mid is moved to the very beginning of the buffer (everything is posioned)
}
if (buffer) {
__sanitizer_annotate_contiguous_container(buffer, buffer + capacity, buffer + capacity, buffer + 1);
// ^ That's NOT correct, `old_mid` should be the very beginning of buffer and here the argument is `buffer + capacity`.
// The correct line is `__sanitizer_annotate_contiguous_container(buffer, buffer + capacity, buffer, buffer + 1);`
} Fixed code is working without the error: https://godbolt.org/z/cjxY5odPW (I had to fix more than just that one line, but all fixes are same.) Also, this code won't generate this error since LLVM 17 thanks to 0b2c0dc63faa, but it's still incorrect. Checks were removed to allow unpoisoning containers memory without crashing the program (in that case, false negatives can happen, but not false positives). Providing incorrect Edit: Unpoisoning the memory by container is important even when you are using a simple wrapper to the default allocator which cleans the memory (set every byte to zero) before freeing it. Memory cannot be poisoned when touched by allocator (unless you explicitly turn off instrumentation). Container unpoisoning memory is a good practice (and required by many allocators), but with default allocators it works without it. __sanitizer_annotate_contiguous_container(buffer, buffer + capacity, buffer + capacity, buffer + capacity); when the container is [partially] poisoned, TL;DR: |
When using container annotations (
__sanitizer_annotate_contiguous_container
) withsizeof(*buffer) < SHADOW_GRANULARITY
ASAN leaves behind non-0 shadow memory state in certain scenarios (e.g. when used withuint32_t
(half word)).The problem boils down to the question whether
is allowed to leave behind non-0 shadow memory state that must be cleaned up by the allocator in case buffer is freed and later reused with a different capacity. From the API description I would have assumed that this is the valid start/end state that is fully cleaned up.
Note that upwards aligning
end
doesn't change anything asbegin
andend
are merely used for containments checks but not for computing the poisoned ranges.This show up as issue in Chromium: https://bugs.chromium.org/p/chromium/issues/detail?id=1292392
Self-contained repro:
Crash:
The text was updated successfully, but these errors were encountered: