Description
Memory for req_info_type
in exec_op
is being allocated using the handler's associated allocator, but is not being freed before calling complete
. This is a violation of one of Asio's composed ops principles.
This has been caught by ubsan when using Boost.Redis together with Boost.Async (I'm exercising the library by rewriting BoostServerTech). Boost.Async uses an internal, per-operation allocator. That is, when you call conn.async_exec(whatever, use_op)
, a stack-based memory pool of 2kb is created. All allocations for this async_exec
will use these 2kb of memory first. Once this async_exec
operation is done, the pool is destroyed. However, the call self.complete
within async_exec
resumes and keeps executing the coroutine that called async_exec
. At this point, async_exec
has a req_info_type
object pointing to memory that has been freed (or re-used). When the shared_ptr<req_info_type>
destructor runs, it will be accessing freed memory.
It's likely that this can be used to build exploits leading to arbitrary code execution.