[llvm-bugs] [Bug 51515] New: [coroutines] [aarch64] ASAN stack-use-after-return when using initializer_list in the loop
via llvm-bugs
llvm-bugs at lists.llvm.org
Tue Aug 17 14:48:45 PDT 2021
https://bugs.llvm.org/show_bug.cgi?id=51515
Bug ID: 51515
Summary: [coroutines] [aarch64] ASAN stack-use-after-return
when using initializer_list in the loop
Product: clang
Version: 12.0
Hardware: PC
OS: Linux
Status: NEW
Severity: normal
Priority: P
Component: C++2a
Assignee: unassignedclangbugs at nondot.org
Reporter: pa.solodovnikov at scylladb.com
CC: blitzrakete at gmail.com, erik.pilkington at gmail.com,
llvm-bugs at lists.llvm.org, richard-llvm at metafoo.co.uk
Created attachment 25152
--> https://bugs.llvm.org/attachment.cgi?id=25152&action=edit
Preprocessed source
The following program will report stack-use-after-return, when compiled with
Clang 12.0.0 (12.0.1, 13.0.0 and trunk, as well) and ASAN enabled:
#include <initializer_list>
...
class resumable {
public:
struct promise_type;
using coro_handle =
std::experimental::coroutine_handle<promise_type>;
resumable(coro_handle& handle) : handle(handle) {}
resumable(resumable&&) = delete;
~resumable() {
handle.destroy();
}
bool resume() {
if (!handle.done()) {
handle.resume();
}
return !handle.done();
}
private:
coro_handle handle;
};
struct resumable::promise_type {
using coro_handle =
std::experimental::coroutine_handle<promise_type>;
auto get_return_object() {
return coro_handle::from_promise(*this);
}
auto initial_suspend() { return
std::experimental::suspend_always(); }
auto final_suspend() noexcept { return
std::experimental::suspend_always(); }
void return_void() {}
void unhandled_exception() {
throw;
}
};
struct test_init_list {
int item;
test_init_list(std::initializer_list<int> items) {
item = *items.begin();
}
};
resumable foo() {
for (int _ : {1, 2}) {
(void)_;
test_init_list x {0}; // <-- Crashes after the first
suspension
co_await std::experimental::suspend_always();
}
}
int main() {
auto p = foo();
while (p.resume());
return 0;
}
Steps to reproduce:
# build
/usr/bin/clang++ -std=c++20 -fsanitize=address -Wall -Werror -Og -g -o
clang_coro_init_list_bug.cc.o -c clang_coro_init_list_bug.cc
# link
/usr/bin/clang++ clang_coro_init_list_bug.cc.o -o
clang_coro_init_list_bug -fsanitize=address
# execute with ASAN
ASAN_OPTIONS='disable_coredump=0:abort_on_error=0:detect_stack_use_after_return=1'
./clang_coro_init_list_bug
Execution result:
=================================================================
==24==ERROR: AddressSanitizer: stack-use-after-return on address 0xffff8630e0e0
at pc 0x0000004eeed0 bp 0xffffdc7a11c0 sp 0xffffdc7a11d8
READ of size 4 at 0xffff8630e0e0 thread T0
#0 0x4eeecc (/home/pa.solodovnikov/clang_coro_init_list_bug_pp+0x4eeecc)
#1 0x4ee964 (/home/pa.solodovnikov/clang_coro_init_list_bug_pp+0x4ee964)
#2 0x4ef170 (/home/pa.solodovnikov/clang_coro_init_list_bug_pp+0x4ef170)
#3 0x4eef58 (/home/pa.solodovnikov/clang_coro_init_list_bug_pp+0x4eef58)
#4 0x4ee698 (/home/pa.solodovnikov/clang_coro_init_list_bug_pp+0x4ee698)
#5 0xffff899a2b18 (/lib64/libc.so.6+0x24b18)
#6 0x421d8c (/home/pa.solodovnikov/clang_coro_init_list_bug_pp+0x421d8c)
Address 0xffff8630e0e0 is located in stack of thread T0 at offset 32 in frame
#0 0x4ee71c (/home/pa.solodovnikov/clang_coro_init_list_bug_pp+0x4ee71c)
This frame has 1 object(s):
[32, 36) 'ref.tmp14' <== Memory access at offset 32 is inside this variable
HINT: this may be a false positive if your program uses some custom stack
unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-use-after-return
(/home/pa.solodovnikov/clang_coro_init_list_bug_pp+0x4eeecc)
Shadow bytes around the buggy address:
0x200ff0c61bc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x200ff0c61bd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x200ff0c61be0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x200ff0c61bf0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x200ff0c61c00: f1 f1 f1 f1 00 f3 f3 f3 f5 f5 f5 f5 f5 f5 f5 f5
=>0x200ff0c61c10: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5[f5]f5 f5 f5
0x200ff0c61c20: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x200ff0c61c30: f1 f1 f1 f1 04 f3 f3 f3 f1 f1 f1 f1 00 00 f3 f3
0x200ff0c61c40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x200ff0c61c50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x200ff0c61c60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==24==ABORTING
Decoded stack trace:
[Backtrace #0]
test_init_list at /home/pa.solodovnikov/clang_coro_init_list_bug.cc:129
foo() at /home/pa.solodovnikov/clang_coro_init_list_bug.cc:136
std::experimental::coroutine_handle<resumable::promise_type>::resume() const at
/home/pa.solodovnikov/clang_coro_init_list_bug.cc:38
resumable::resume() at /home/pa.solodovnikov/clang_coro_init_list_bug.cc:102
main at /home/pa.solodovnikov/clang_coro_init_list_bug.cc:143
__libc_start_main at ??:?
_start at ??:?
This points to the following place in the code, where initializer list data is
accessed:
test_init_list(std::initializer_list<int> items) {
item = *items.begin();
}
List initialization is broken after the first coroutine suspension. I have
added debug printouts around the crash site:
test_init_list(std::initializer_list<int> items) {
std::cout << "initializer list address: " << &items << std::endl;
std::cout << "initializer list data pointer: " << std::data(items) <<
std::endl;
item = *items.begin();
}
This shows, that the address to the underlying storage is the same (obviously
points to garbage after a coroutine is resumed):
initializer list address: 0xffff85fbd120
initializer list data pointer: 0xffff85fbd0e0
initializer list address: 0xffff85fbd220
initializer list data pointer: 0xffff85fbd0e0
The problem only happens with the following combination: aarch64 target, ASAN
enabled (-fsanitize=address), -Og optimization level (-Oz or -Os are also
affected). Tested with libstdc++ 11.2.1.
When built with GCC 11.2.1, the code compiles and executes without errors.
I have also attached a preprocessed version of source code.
--
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20210817/a45d574b/attachment-0001.html>
More information about the llvm-bugs
mailing list