Skip to content

fix(io_uring): remove type-punning UB in buffer→iovec conversion (#291)#294

Merged
mvandeberg merged 1 commit into
cppalliance:develop-2from
mvandeberg:pr/291-fix-punning-ub
Jun 30, 2026
Merged

fix(io_uring): remove type-punning UB in buffer→iovec conversion (#291)#294
mvandeberg merged 1 commit into
cppalliance:develop-2from
mvandeberg:pr/291-fix-punning-ub

Conversation

@mvandeberg

Copy link
Copy Markdown
Contributor

The io_uring backend declared iovec iovecs[] storage, then reinterpret_cast it to capy::mutable_buffer* so copy_to could populate it, and later handed the same storage to the kernel as iovec. Even with layout-compatible types this is undefined behavior: no mutable_buffer object is ever created in that storage, and mutable_buffer is not an implicit-lifetime type, so std::start_lifetime_as_array cannot rescue it either.

Add a copy_to_iovec helper that copies into a real mutable_buffer scratch array and then translates field by field into the caller's iovec array — the same safe pattern the reactor and posix backends already use, factored into one place since io_uring had 14 call sites. Replace all 14 reinterpret_cast sites across io_uring_types.hpp, io_uring_file_ops.hpp, io_uring_dgram_ops.hpp, and io_uring_socket_ops.hpp.

Also fix the buffer_param docstring, whose two @code examples demonstrated the same reinterpret_cast<iovec*> pun as "OK"/"CORRECT" — a recurrence trap. They now show the field-by-field copy and a @note explaining why the cast is UB.

…alliance#291)

The io_uring backend declared `iovec iovecs[]` storage, then
`reinterpret_cast` it to `capy::mutable_buffer*` so `copy_to` could
populate it, and later handed the same storage to the kernel as
`iovec`. Even with layout-compatible types this is undefined behavior:
no `mutable_buffer` object is ever created in that storage, and
`mutable_buffer` is not an implicit-lifetime type, so
`std::start_lifetime_as_array` cannot rescue it either.

Add a `copy_to_iovec` helper that copies into a real `mutable_buffer`
scratch array and then translates field by field into the caller's
`iovec` array — the same safe pattern the reactor and posix backends
already use, factored into one place since io_uring had 14 call sites.
Replace all 14 `reinterpret_cast` sites across io_uring_types.hpp,
io_uring_file_ops.hpp, io_uring_dgram_ops.hpp, and io_uring_socket_ops.hpp.

Also fix the buffer_param docstring, whose two `@code` examples
demonstrated the same `reinterpret_cast<iovec*>` pun as "OK"/"CORRECT"
— a recurrence trap. They now show the field-by-field copy and a
`@note` explaining why the cast is UB.
@cppalliance-bot

Copy link
Copy Markdown

An automated preview of the documentation is available at https://294.corosio.prtest3.cppalliance.org/index.html

If more commits are pushed to the pull request, the docs will rebuild at the same URL.

2026-06-30 19:33:57 UTC

@cppalliance-bot

Copy link
Copy Markdown

GCOVR code coverage report https://294.corosio.prtest3.cppalliance.org/gcovr/index.html
LCOV code coverage report https://294.corosio.prtest3.cppalliance.org/genhtml/index.html
Coverage Diff Report https://294.corosio.prtest3.cppalliance.org/diff-report/index.html

Build time: 2026-06-30 19:44:52 UTC

@mvandeberg mvandeberg merged commit abcf24b into cppalliance:develop-2 Jun 30, 2026
38 checks passed
@github-project-automation github-project-automation Bot moved this from Backlog to Done in Beast2 Jun 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants