Skip to content

Commit

Permalink
fix: Avoid ub when casting function pointer to regular pointer
Browse files Browse the repository at this point in the history
  • Loading branch information
Tradias committed Oct 6, 2023
1 parent 05ce0ee commit cd384a4
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 17 deletions.
11 changes: 4 additions & 7 deletions src/agrpc/detail/basic_sender.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ class BasicSenderRunningOperation : public detail::BaseForSenderImplementationTy
template <AllocationType, int Id>
void set_on_complete() noexcept
{
detail::OperationBaseAccess::get_on_complete(*this) = &do_complete<Id>;
detail::OperationBaseAccess::set_on_complete(*this, &do_complete<Id>);
}

template <AllocationType, class... Args>
Expand All @@ -169,17 +169,14 @@ class BasicSenderRunningOperation : public detail::BaseForSenderImplementationTy
detail::satisfy_receiver(static_cast<Receiver&&>(receiver()), static_cast<Args&&>(args)...);
}

void put_into_scratch_space(void* ptr) noexcept
{
detail::OperationBaseAccess::get_on_complete(*this) = reinterpret_cast<detail::OperationOnComplete>(ptr);
}
void put_into_scratch_space(void* ptr) noexcept { detail::OperationBaseAccess::set_scratch_space(*this, ptr); }

[[nodiscard]] void* get_scratch_space() const noexcept
{
return reinterpret_cast<void*>(detail::OperationBaseAccess::get_on_complete(*this));
return detail::OperationBaseAccess::get_scratch_space(*this);
}

void restore_scratch_space() noexcept { detail::OperationBaseAccess::get_on_complete(*this) = &do_complete; }
void restore_scratch_space() noexcept { detail::OperationBaseAccess::set_on_complete(*this, &do_complete); }

private:
detail::CompressedPair<detail::CompressedPair<Receiver, StopCallback>, Implementation> impl_;
Expand Down
18 changes: 16 additions & 2 deletions src/agrpc/detail/operation_base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,11 @@ class OperationBase
private:
friend detail::OperationBaseAccess;

OperationOnComplete on_complete_;
union
{
OperationOnComplete on_complete_;
void* scratch_space_;
};
};

class QueueableOperationBase : public detail::OperationBase
Expand All @@ -71,9 +75,19 @@ class QueueableOperationBase : public detail::OperationBase

struct OperationBaseAccess
{
static auto& get_on_complete(detail::OperationBase& operation) noexcept { return operation.on_complete_; }
static void set_on_complete(detail::OperationBase& operation, OperationOnComplete on_complete) noexcept
{
operation.on_complete_ = on_complete;
}

static auto get_on_complete(const detail::OperationBase& operation) noexcept { return operation.on_complete_; }

static void set_scratch_space(detail::OperationBase& operation, void* ptr) noexcept
{
operation.scratch_space_ = ptr;
}

static void* get_scratch_space(const detail::OperationBase& operation) noexcept { return operation.scratch_space_; }
};

[[nodiscard]] constexpr bool is_ok(OperationResult result) noexcept { return result == OperationResult::OK; }
Expand Down
4 changes: 2 additions & 2 deletions src/agrpc/detail/repeatedly_request_context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@ class RepeatedlyRequestOperation : public detail::QueueableOperationBase,

void add_completing_operation(agrpc::GrpcContext& grpc_context)
{
detail::OperationBaseAccess::get_on_complete(*this) =
detail::DO_COMPLETE_NO_ARG_HANDLER<RepeatedlyRequestOperation>;
detail::OperationBaseAccess::set_on_complete(*this,
detail::DO_COMPLETE_NO_ARG_HANDLER<RepeatedlyRequestOperation>);
detail::GrpcContextImplementation::add_local_operation(grpc_context, this);
}

Expand Down
2 changes: 1 addition & 1 deletion src/agrpc/detail/sender_implementation_operation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ struct SenderImplementationOperation : public detail::BaseForSenderImplementatio
template <AllocationType AllocType, int Id>
void set_on_complete() noexcept
{
detail::OperationBaseAccess::get_on_complete(*this) = &do_complete<AllocType, Id>;
detail::OperationBaseAccess::set_on_complete(*this, &do_complete<AllocType, Id>);
}

template <AllocationType AllocType, class... Args>
Expand Down
10 changes: 5 additions & 5 deletions src/agrpc/detail/server_write_reactor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,15 @@ class ServerWriteReactor : public detail::ServerWriteReactorStepBase, public det

void write(const Response& response)
{
get_on_complete() = &ServerWriteReactor::do_write_done;
set_on_complete(&ServerWriteReactor::do_write_done);
writer_.Write(response, static_cast<StepBase*>(this));
}

[[nodiscard]] bool is_finished() const noexcept { return &ServerWriteReactor::do_finish_done == get_on_complete(); }

void finish(const grpc::Status& status)
{
get_on_complete() = &ServerWriteReactor::do_finish_done;
set_on_complete(&ServerWriteReactor::do_finish_done);
writer_.Finish(status, static_cast<StepBase*>(this));
}

Expand All @@ -80,17 +80,17 @@ class ServerWriteReactor : public detail::ServerWriteReactorStepBase, public det
private:
auto get_allocator() const noexcept { return grpc_context_->get_allocator(); }

auto& get_on_complete() noexcept
void set_on_complete(detail::OperationOnComplete on_complete) noexcept
{
return detail::OperationBaseAccess::get_on_complete(*static_cast<StepBase*>(this));
detail::OperationBaseAccess::set_on_complete(*static_cast<StepBase*>(this), on_complete);
}

auto get_on_complete() const noexcept
{
return detail::OperationBaseAccess::get_on_complete(*static_cast<const StepBase*>(this));
}

void set_step_done() noexcept { get_on_complete() = nullptr; }
void set_step_done() noexcept { set_on_complete(nullptr); }

bool is_finishing_or_writing() const noexcept { return nullptr != get_on_complete(); }

Expand Down

0 comments on commit cd384a4

Please sign in to comment.