From 3d9c79f65ff03db3af3ede2f7ad94792411155c9 Mon Sep 17 00:00:00 2001 From: a-maurice Date: Thu, 27 Aug 2026 14:13:22 -0700 Subject: [PATCH 1/3] Fix CFI icall violation in Future callbacks --- .../include/firebase/internal/future_impl.h | 61 ++++++++++++++++--- 1 file changed, 53 insertions(+), 8 deletions(-) diff --git a/app/src/include/firebase/internal/future_impl.h b/app/src/include/firebase/internal/future_impl.h index 59e7771d01..37941f11d9 100644 --- a/app/src/include/firebase/internal/future_impl.h +++ b/app/src/include/firebase/internal/future_impl.h @@ -152,21 +152,54 @@ class CompletionCallbackHandle { void (*user_data_delete_fn_)(void*); }; +template +struct TypedCompletionCallbackData { + typename Future::TypedCompletionCallback callback; + void* user_data; +}; + +template +inline void TypedCompletionCallbackTrampoline(const FutureBase& future, + void* data_ptr) { + auto* data = static_cast*>(data_ptr); + if (data != nullptr && data->callback != nullptr) { + data->callback(static_cast&>(future), data->user_data); + } +} + +template +inline void DeleteTypedCompletionCallbackData(void* data_ptr) { + delete static_cast*>(data_ptr); +} + } // namespace detail template void Future::OnCompletion(TypedCompletionCallback callback, void* user_data) const { - FutureBase::OnCompletion(reinterpret_cast(callback), - user_data); + MutexLock lock(mutex_); + if (api_ != nullptr) { + if (callback == nullptr) { + api_->AddCompletionCallback(handle_, nullptr, nullptr, nullptr, + /*clear_existing_callbacks=*/true); + } else { + auto* data = + new detail::TypedCompletionCallbackData{callback, user_data}; + api_->AddCompletionCallback( + handle_, detail::TypedCompletionCallbackTrampoline, data, + detail::DeleteTypedCompletionCallbackData, + /*clear_existing_callbacks=*/true); + } + } } #if defined(FIREBASE_USE_STD_FUNCTION) template inline void Future::OnCompletion( std::function&)> callback) const { - FutureBase::OnCompletion( - *reinterpret_cast*>(&callback)); + FutureBase::OnCompletion([callback](const FutureBase& future) { + callback(static_cast&>(future)); + }); } #endif // defined(FIREBASE_USE_STD_FUNCTION) @@ -174,16 +207,28 @@ inline void Future::OnCompletion( template FutureBase::CompletionCallbackHandle Future::AddOnCompletion( TypedCompletionCallback callback, void* user_data) const { - return FutureBase::AddOnCompletion( - reinterpret_cast(callback), user_data); + MutexLock lock(mutex_); + if (api_ != nullptr) { + if (callback == nullptr) { + return CompletionCallbackHandle(); + } + auto* data = + new detail::TypedCompletionCallbackData{callback, user_data}; + return api_->AddCompletionCallback( + handle_, detail::TypedCompletionCallbackTrampoline, data, + detail::DeleteTypedCompletionCallbackData, + /*clear_existing_callbacks=*/false); + } + return CompletionCallbackHandle(); } #if defined(FIREBASE_USE_STD_FUNCTION) template inline FutureBase::CompletionCallbackHandle Future::AddOnCompletion( std::function&)> callback) const { - return FutureBase::AddOnCompletion( - *reinterpret_cast*>(&callback)); + return FutureBase::AddOnCompletion([callback](const FutureBase& future) { + callback(static_cast&>(future)); + }); } #endif // defined(FIREBASE_USE_STD_FUNCTION) From e7690b09c61b1cabf4679822d93db058c7185510 Mon Sep 17 00:00:00 2001 From: a-maurice Date: Mon, 31 Aug 2026 12:44:12 -0700 Subject: [PATCH 2/3] Update future_impl.h --- app/src/include/firebase/internal/future_impl.h | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/app/src/include/firebase/internal/future_impl.h b/app/src/include/firebase/internal/future_impl.h index 37941f11d9..216c57143d 100644 --- a/app/src/include/firebase/internal/future_impl.h +++ b/app/src/include/firebase/internal/future_impl.h @@ -180,7 +180,7 @@ void Future::OnCompletion(TypedCompletionCallback callback, MutexLock lock(mutex_); if (api_ != nullptr) { if (callback == nullptr) { - api_->AddCompletionCallback(handle_, nullptr, nullptr, nullptr, + api_->AddCompletionCallback(handle_, [](const FutureBase&, void*){}, nullptr, nullptr, /*clear_existing_callbacks=*/true); } else { auto* data = @@ -197,9 +197,13 @@ void Future::OnCompletion(TypedCompletionCallback callback, template inline void Future::OnCompletion( std::function&)> callback) const { - FutureBase::OnCompletion([callback](const FutureBase& future) { - callback(static_cast&>(future)); - }); + if (!callback) { + FutureBase::OnCompletion([](const FutureBase&, void*){}, nullptr); + } else { + FutureBase::OnCompletion([callback](const FutureBase& future) { + callback(static_cast&>(future)); + }); + } } #endif // defined(FIREBASE_USE_STD_FUNCTION) @@ -226,6 +230,9 @@ FutureBase::CompletionCallbackHandle Future::AddOnCompletion( template inline FutureBase::CompletionCallbackHandle Future::AddOnCompletion( std::function&)> callback) const { + if (!callback) { + return CompletionCallbackHandle(); + } return FutureBase::AddOnCompletion([callback](const FutureBase& future) { callback(static_cast&>(future)); }); From d6dfa41c85ba0494905974603e421c6059f88949 Mon Sep 17 00:00:00 2001 From: a-maurice Date: Mon, 31 Aug 2026 12:44:43 -0700 Subject: [PATCH 3/3] Update future_impl.h --- app/src/include/firebase/internal/future_impl.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/src/include/firebase/internal/future_impl.h b/app/src/include/firebase/internal/future_impl.h index 216c57143d..a328aaf094 100644 --- a/app/src/include/firebase/internal/future_impl.h +++ b/app/src/include/firebase/internal/future_impl.h @@ -180,8 +180,9 @@ void Future::OnCompletion(TypedCompletionCallback callback, MutexLock lock(mutex_); if (api_ != nullptr) { if (callback == nullptr) { - api_->AddCompletionCallback(handle_, [](const FutureBase&, void*){}, nullptr, nullptr, - /*clear_existing_callbacks=*/true); + api_->AddCompletionCallback( + handle_, [](const FutureBase&, void*) {}, nullptr, nullptr, + /*clear_existing_callbacks=*/true); } else { auto* data = new detail::TypedCompletionCallbackData{callback, user_data}; @@ -198,7 +199,7 @@ template inline void Future::OnCompletion( std::function&)> callback) const { if (!callback) { - FutureBase::OnCompletion([](const FutureBase&, void*){}, nullptr); + FutureBase::OnCompletion([](const FutureBase&, void*) {}, nullptr); } else { FutureBase::OnCompletion([callback](const FutureBase& future) { callback(static_cast&>(future));