diff options
author | Benoit Jacob <benoitjacob@google.com> | 2022-01-21 19:17:21 +0300 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2022-01-21 19:17:48 +0300 |
commit | 2d950b3bfa7ebfbe7a97ecb44b1cc4da5ac1d6f0 (patch) | |
tree | 85a3920793e0f6ef80c9b1efeb14dac14adc75b5 | |
parent | abaaa6a6a5515cfe958cf7b32ae1f2e5ca1b962f (diff) |
Accomodate Clang's CFI sanitizer
It was complaining that the `TrMulTask* tasks` pointer was temporarily pointing to garbage as we first set it to point to the allocated buffer, then perform the actual TrMulTask object constructions using placement-new. Rewritten so that the pointer is kept a `char*` pointer during this allocation and placement-new business, and only assigned to a TrMulTasks* pointer at the end.
Note: this is *not* a strict-aliasing issue. The CFI diagnostic here is unaffected by `-f[no-]strict-aliasing` and the reason why this isn't a strict-aliasing violation is that the C++ spec makes an exception for `char` and a couple of other byte types, allowing to make byte buffers alias objects of other types. So CFI is going beyond the C++ spec here --- this isn't an undefined-behavior report. This is apparently trying to enforce that if pointers are set at all then they must be set to point to a valid object of their element type. At least for types that have a vtable.
PiperOrigin-RevId: 423326986
-rw-r--r-- | ruy/trmul.cc | 18 |
1 files changed, 10 insertions, 8 deletions
diff --git a/ruy/trmul.cc b/ruy/trmul.cc index 602660b..dbf5feb 100644 --- a/ruy/trmul.cc +++ b/ruy/trmul.cc @@ -377,20 +377,22 @@ void TrMul(Ctx* ctx, TrMulParams* params) { // reservation granule. std::atomic<int>* atomic_block_id; main_allocator->Allocate(1, &atomic_block_id); - - // Create task objects. - TrMulTask* tasks; - main_allocator->Allocate(thread_count, &tasks); - atomic_block_id->store(thread_count); + // Create task objects. We allocate a single buffer and then use placement-new + // to construct N TrMulTask objects within it. To avoid having the Clang CFI + // sanitizer complain about a TrMulTask* pointer temporarily pointing to + // garbage, we keep the pointer a plain char* until finished constructing. + char* tasks_buf = + main_allocator->Allocate<char>(thread_count * sizeof(TrMulTask)); for (int i = 0; i < thread_count; i++) { auto* allocator = ctx->GetThreadSpecificAllocator(i); auto* tuning_resolver = ctx->GetThreadSpecificTuningResolver(i); - new (tasks + i) TrMulTask(params, block_map, atomic_block_id, i, - need_atomics, packing_status, tuning_resolver, - allocator, ctx->mutable_cpuinfo()); + new (tasks_buf + i * sizeof(TrMulTask)) TrMulTask( + params, block_map, atomic_block_id, i, need_atomics, packing_status, + tuning_resolver, allocator, ctx->mutable_cpuinfo()); } + TrMulTask* tasks = reinterpret_cast<TrMulTask*>(tasks_buf); // Do the computation. ctx->mutable_thread_pool()->Execute(thread_count, tasks); |