Skip to content

Invalid memory read in io_context::executor_type::post #290

Description

@anarthal

The continuation version of io_context::executor_type::post [1] seems to cause an invalid read when submitting operations that don't inherit from continuation_op. try_from_continuation [2] will attempt to read a magic number. In continuation_op, the magic is before the continuation member [3]. If the submitted operation doesn't inherit from continuation_op, this leads to reading potentially unmapped memory.

Reproducer (build with -fsanitize=address):

#include <boost/capy/continuation.hpp>
#include <boost/capy/ex/run_async.hpp>
#include <boost/capy/task.hpp>
#include <boost/corosio/io_context.hpp>

#include <coroutine>
#include <iostream>
#include <memory>

namespace capy = boost::capy;
namespace corosio = boost::corosio;
using namespace std::chrono_literals;

struct my_awaitable {
   capy::continuation* cont;

   bool await_ready() const { return false; }
   std::coroutine_handle<> await_suspend(
      std::coroutine_handle<> h,
      capy::io_env const* env) noexcept
   {
      cont->h = h;
      env->executor.post(*cont);
      return std::noop_coroutine();
   }

   int await_resume() const { return 42; }
};

capy::task<void> co_main()
{
   auto cont = std::make_unique<capy::continuation>();
   my_awaitable aw{cont.get()};
   int v = co_await aw;
   std::cout << "The value is: " << v << std::endl;
}

int main()
{
   corosio::io_context ctx;

   capy::run_async(
      ctx.get_executor(),
      []() {
         std::cout << "Done\n";
      },
      [](std::exception_ptr exc) {
         try {
            std::rethrow_exception(exc);
         } catch (const std::exception& e) {
            std::cerr << "Error: " << e.what() << std::endl;
         }
         exit(1);
      })(co_main());

   ctx.run();
}

Output:

==479971==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x502000004c08 at pc 0x5555560d428e bp 0x7fffffffbe70 sp 0x7fffffffbe60
READ of size 4 at 0x502000004c08 thread T0
    #0 0x5555560d428d in boost::corosio::detail::continuation_op::try_from_continuation(boost::capy::continuation&) [redacted]/boost-root/libs/corosio/include/boost/corosio/detail/continuation_op.hpp:105
    #1 0x5555560d56fe in boost::corosio::io_context::executor_type::post(boost::capy::continuation&) const [redacted]/boost-root/libs/corosio/include/boost/corosio/io_context.hpp:604
    #2 0x5555560da0de in boost::capy::detail::vtable_for<boost::corosio::io_context::executor_type>::{lambda(void const*, boost::capy::continuation&)#1}::operator()(void const*, boost::capy::continuation&) const [redacted]/boost-root/libs/capy/include/boost/capy/ex/executor_ref.hpp:57
    #3 0x5555560da10e in boost::capy::detail::vtable_for<boost::corosio::io_context::executor_type>::{lambda(void const*, boost::capy::continuation&)#1}::_FUN(void const*, boost::capy::continuation&) [redacted]/boost-root/libs/capy/include/boost/capy/ex/executor_ref.hpp:56
    #4 0x5555560d1aa7 in boost::capy::executor_ref::post(boost::capy::continuation&) const [redacted]/boost-root/libs/capy/include/boost/capy/ex/executor_ref.hpp:234
    #5 0x5555560d6478 in my_awaitable::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::io_env const*) [redacted]/boost-root/libs/redis/example/corosio_intro.cpp:29
    #6 0x5555560d7421 in auto boost::capy::task<void>::promise_type::transform_awaiter<my_awaitable&>::await_suspend<boost::capy::task<void>::promise_type>(std::__n4861::coroutine_handle<boost::capy::task<void>::promise_type>) [redacted]/boost-root/libs/capy/include/boost/capy/task.hpp:208
    #7 0x5555560ca66a in co_main [redacted]/boost-root/libs/redis/example/corosio_intro.cpp:40
    #8 0x5555560d0db7 in std::__n4861::coroutine_handle<void>::resume() const /usr/include/c++/14/coroutine:137
    #9 0x5555560f605b in boost::corosio::detail::reactor_scheduler::post(std::__n4861::coroutine_handle<void>) const::post_handler::operator()() [redacted]/boost-root/libs/corosio/include/boost/corosio/native/detail/reactor/reactor_scheduler.hpp:495
    #10 0x55555610047a in boost::corosio::detail::reactor_scheduler::do_one(boost::corosio::detail::conditionally_enabled_mutex::scoped_lock&, long, boost::corosio::detail::reactor_scheduler_context*) [redacted]/boost-root/libs/corosio/include/boost/corosio/native/detail/reactor/reactor_scheduler.hpp:920
    #11 0x5555560f83d5 in boost::corosio::detail::reactor_scheduler::run() [redacted]/boost-root/libs/corosio/include/boost/corosio/native/detail/reactor/reactor_scheduler.hpp:584
    #12 0x5555560d4670 in boost::corosio::io_context::run() [redacted]/boost-root/libs/corosio/include/boost/corosio/io_context.hpp:351
    #13 0x5555560cbdfe in main [redacted]/boost-root/libs/redis/example/corosio_intro.cpp:62
    #14 0x7ffff622a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #15 0x7ffff622a28a in __libc_start_main_impl ../csu/libc-start.c:360
    #16 0x5555560c9464 in _start ([redacted]/boost-root/libs/redis/__build/gcc-14/Debug/stage/bin/boost_redis_corosio_intro+0xb75464) (BuildId: a1274b59a9096f9b2a64c08bea4608f32a9721de)

0x502000004c08 is located 8 bytes before 16-byte region [0x502000004c10,0x502000004c20)
allocated by thread T0 here:
    #0 0x7ffff78fe548 in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:95
    #1 0x5555560d657d in std::__detail::_MakeUniq<boost::capy::continuation>::__single_object std::make_unique<boost::capy::continuation>() /usr/include/c++/14/bits/unique_ptr.h:1076
    #2 0x5555560ca1d8 in co_main [redacted]/boost-root/libs/redis/example/corosio_intro.cpp:38
    #3 0x5555560d0db7 in std::__n4861::coroutine_handle<void>::resume() const /usr/include/c++/14/coroutine:137
    #4 0x5555560f605b in boost::corosio::detail::reactor_scheduler::post(std::__n4861::coroutine_handle<void>) const::post_handler::operator()() [redacted]/boost-root/libs/corosio/include/boost/corosio/native/detail/reactor/reactor_scheduler.hpp:495
    #5 0x55555610047a in boost::corosio::detail::reactor_scheduler::do_one(boost::corosio::detail::conditionally_enabled_mutex::scoped_lock&, long, boost::corosio::detail::reactor_scheduler_context*) [redacted]/boost-root/libs/corosio/include/boost/corosio/native/detail/reactor/reactor_scheduler.hpp:920
    #6 0x5555560f83d5 in boost::corosio::detail::reactor_scheduler::run() [redacted]/boost-root/libs/corosio/include/boost/corosio/native/detail/reactor/reactor_scheduler.hpp:584
    #7 0x5555560d4670 in boost::corosio::io_context::run() [redacted]/boost-root/libs/corosio/include/boost/corosio/io_context.hpp:351
    #8 0x5555560cbdfe in main [redacted]/boost-root/libs/redis/example/corosio_intro.cpp:62
    #9 0x7ffff622a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #10 0x7ffff622a28a in __libc_start_main_impl ../csu/libc-start.c:360
    #11 0x5555560c9464 in _start ([redacted]/boost-root/libs/redis/__build/gcc-14/Debug/stage/bin/boost_redis_corosio_intro+0xb75464) (BuildId: a1274b59a9096f9b2a64c08bea4608f32a9721de)

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

Status
In progress

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions