Skip to content
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

Fix __stop_state double delete. (fix #42) #43

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Grumpfy
Copy link

@Grumpfy Grumpfy commented Jun 16, 2021

Repro steps:

  • create a stop_source
  • get two stop tokens
  • destroy the source
  • destroy one of the stop_token (the internal state is deleted)
  • destroy the second stop_token (double delete of the internal state)

@Grumpfy Grumpfy changed the title Fix __stop_state double delete. Fix __stop_state double delete. (fix #42) Jun 16, 2021
@Grumpfy
Copy link
Author

Grumpfy commented Jun 16, 2021

Issue: #42

@Grumpfy
Copy link
Author

Grumpfy commented Jun 16, 2021

a concrete example:

TEST(future, stop_token) {
	std::stop_source source;
	auto token1 = source.get_token();
	auto token2 = source.get_token();
	source = std::stop_source{};
}

And the issue highlighted by clang memory sanitizer:

=================================================================
==66056==ERROR: AddressSanitizer: heap-use-after-free on address 0x60300000ca30 at pc 0x00010cfb3888 bp 0x7ffee2c87e80 sp 0x7ffee2c87e78
WRITE of size 8 at 0x60300000ca30 thread T0
    #0 0x10cfb3887 in unsigned long long std::__1::__cxx_atomic_fetch_sub<unsigned long long>(std::__1::__cxx_atomic_base_impl<unsigned long long>*, unsigned long long, std::__1::memory_order) atomic:1069
    #1 0x10cfb3725 in std::__1::__atomic_base<unsigned long long, true>::fetch_sub(unsigned long long, std::__1::memory_order) atomic:1717
    #2 0x10cfb39c8 in std::__stop_state::__remove_token_reference() stop_token.hpp:60
    #3 0x10cfb398e in std::stop_token::~stop_token() stop_token.hpp:352
    #4 0x10cfb29a4 in std::stop_token::~stop_token() stop_token.hpp:350
    #5 0x10cfb25d1 in (anonymous namespace)::future_stop_token_Test::TestBody() future.cpp:54
    #6 0x10d0761a7 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)+0x47 (test_concurrency:x86_64+0x1000ff1a7)
    #7 0x10d0760fe in testing::Test::Run()+0x39e (test_concurrency:x86_64+0x1000ff0fe)
    #8 0x10d07797f in testing::TestInfo::Run()+0x3bf (test_concurrency:x86_64+0x10010097f)
    #9 0x10d078406 in testing::TestSuite::Run()+0x106 (test_concurrency:x86_64+0x100101406)
    #10 0x10d085da6 in testing::internal::UnitTestImpl::RunAllTests()+0x766 (test_concurrency:x86_64+0x10010eda6)
    #11 0x10d0854a7 in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)+0x47 (test_concurrency:x86_64+0x10010e4a7)
    #12 0x10d08542b in testing::UnitTest::Run()+0x6b (test_concurrency:x86_64+0x10010e42b)
    #13 0x10d064590 in RUN_ALL_TESTS() gtest.h:2478
    #14 0x10d064508 in main main.cpp:10
    #15 0x7fff2077ff3c in start+0x0 (libdyld.dylib:x86_64+0x15f3c)

0x60300000ca30 is located 0 bytes inside of 24-byte region [0x60300000ca30,0x60300000ca48)
freed by thread T0 here:
    #0 0x10dc210bd in wrap__ZdlPv+0x7d (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x550bd)
    #1 0x10cfb39fa in std::__stop_state::__remove_token_reference() stop_token.hpp:62
    #2 0x10cfb398e in std::stop_token::~stop_token() stop_token.hpp:352
    #3 0x10cfb29a4 in std::stop_token::~stop_token() stop_token.hpp:350
    #4 0x10cfb25c0 in (anonymous namespace)::future_stop_token_Test::TestBody() future.cpp:54
    #5 0x10d0761a7 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)+0x47 (test_concurrency:x86_64+0x1000ff1a7)
    #6 0x10d0760fe in testing::Test::Run()+0x39e (test_concurrency:x86_64+0x1000ff0fe)
    #7 0x10d07797f in testing::TestInfo::Run()+0x3bf (test_concurrency:x86_64+0x10010097f)
    #8 0x10d078406 in testing::TestSuite::Run()+0x106 (test_concurrency:x86_64+0x100101406)
    #9 0x10d085da6 in testing::internal::UnitTestImpl::RunAllTests()+0x766 (test_concurrency:x86_64+0x10010eda6)
    #10 0x10d0854a7 in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)+0x47 (test_concurrency:x86_64+0x10010e4a7)
    #11 0x10d08542b in testing::UnitTest::Run()+0x6b (test_concurrency:x86_64+0x10010e42b)
    #12 0x10d064590 in RUN_ALL_TESTS() gtest.h:2478
    #13 0x10d064508 in main main.cpp:10
    #14 0x7fff2077ff3c in start+0x0 (libdyld.dylib:x86_64+0x15f3c)

previously allocated by thread T0 here:
    #0 0x10dc20c9d in wrap__Znwm+0x7d (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x54c9d)
    #1 0x10cfb29cd in std::stop_source::stop_source() stop_token.hpp:415
    #2 0x10cfb2764 in std::stop_source::stop_source() stop_token.hpp:415
    #3 0x10cfb2555 in (anonymous namespace)::future_stop_token_Test::TestBody() future.cpp:50
    #4 0x10d0761a7 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*)+0x47 (test_concurrency:x86_64+0x1000ff1a7)
    #5 0x10d0760fe in testing::Test::Run()+0x39e (test_concurrency:x86_64+0x1000ff0fe)
    #6 0x10d07797f in testing::TestInfo::Run()+0x3bf (test_concurrency:x86_64+0x10010097f)
    #7 0x10d078406 in testing::TestSuite::Run()+0x106 (test_concurrency:x86_64+0x100101406)
    #8 0x10d085da6 in testing::internal::UnitTestImpl::RunAllTests()+0x766 (test_concurrency:x86_64+0x10010eda6)
    #9 0x10d0854a7 in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)+0x47 (test_concurrency:x86_64+0x10010e4a7)
    #10 0x10d08542b in testing::UnitTest::Run()+0x6b (test_concurrency:x86_64+0x10010e42b)
    #11 0x10d064590 in RUN_ALL_TESTS() gtest.h:2478
    #12 0x10d064508 in main main.cpp:10
    #13 0x7fff2077ff3c in start+0x0 (libdyld.dylib:x86_64+0x15f3c)

SUMMARY: AddressSanitizer: heap-use-after-free atomic:1069 in unsigned long long std::__1::__cxx_atomic_fetch_sub<unsigned long long>(std::__1::__cxx_atomic_base_impl<unsigned long long>*, unsigned long long, std::__1::memory_order)

@Grumpfy
Copy link
Author

Grumpfy commented Jun 21, 2021

A discussion about the proposed fix is available here: #39

@kalman5
Copy link
Contributor

kalman5 commented Jun 22, 2021

As reported in #39 I would add a new __emptyState and use that instead.

@josuttis
Copy link
Owner

josuttis commented Jun 23, 2021 via email

@Grumpfy
Copy link
Author

Grumpfy commented Jun 23, 2021

I agree with you Gaetano, the code could and should be more expressive. I'll do the suggested update.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants