Skip to content

Commit 79c2210

Browse files
authored
Fix CFI icall violation in Future callbacks (#1914)
* Fix CFI icall violation in Future callbacks * Update future_impl.h * Update future_impl.h
1 parent bd57f12 commit 79c2210

1 file changed

Lines changed: 61 additions & 8 deletions

File tree

app/src/include/firebase/internal/future_impl.h

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -152,38 +152,91 @@ class CompletionCallbackHandle {
152152
void (*user_data_delete_fn_)(void*);
153153
};
154154

155+
template <typename T>
156+
struct TypedCompletionCallbackData {
157+
typename Future<T>::TypedCompletionCallback callback;
158+
void* user_data;
159+
};
160+
161+
template <typename T>
162+
inline void TypedCompletionCallbackTrampoline(const FutureBase& future,
163+
void* data_ptr) {
164+
auto* data = static_cast<TypedCompletionCallbackData<T>*>(data_ptr);
165+
if (data != nullptr && data->callback != nullptr) {
166+
data->callback(static_cast<const Future<T>&>(future), data->user_data);
167+
}
168+
}
169+
170+
template <typename T>
171+
inline void DeleteTypedCompletionCallbackData(void* data_ptr) {
172+
delete static_cast<TypedCompletionCallbackData<T>*>(data_ptr);
173+
}
174+
155175
} // namespace detail
156176

157177
template <class T>
158178
void Future<T>::OnCompletion(TypedCompletionCallback callback,
159179
void* user_data) const {
160-
FutureBase::OnCompletion(reinterpret_cast<CompletionCallback>(callback),
161-
user_data);
180+
MutexLock lock(mutex_);
181+
if (api_ != nullptr) {
182+
if (callback == nullptr) {
183+
api_->AddCompletionCallback(
184+
handle_, [](const FutureBase&, void*) {}, nullptr, nullptr,
185+
/*clear_existing_callbacks=*/true);
186+
} else {
187+
auto* data =
188+
new detail::TypedCompletionCallbackData<T>{callback, user_data};
189+
api_->AddCompletionCallback(
190+
handle_, detail::TypedCompletionCallbackTrampoline<T>, data,
191+
detail::DeleteTypedCompletionCallbackData<T>,
192+
/*clear_existing_callbacks=*/true);
193+
}
194+
}
162195
}
163196

164197
#if defined(FIREBASE_USE_STD_FUNCTION)
165198
template <class ResultType>
166199
inline void Future<ResultType>::OnCompletion(
167200
std::function<void(const Future<ResultType>&)> callback) const {
168-
FutureBase::OnCompletion(
169-
*reinterpret_cast<std::function<void(const FutureBase&)>*>(&callback));
201+
if (!callback) {
202+
FutureBase::OnCompletion([](const FutureBase&, void*) {}, nullptr);
203+
} else {
204+
FutureBase::OnCompletion([callback](const FutureBase& future) {
205+
callback(static_cast<const Future<ResultType>&>(future));
206+
});
207+
}
170208
}
171209
#endif // defined(FIREBASE_USE_STD_FUNCTION)
172210

173211
#if defined(INTERNAL_EXPERIMENTAL)
174212
template <class T>
175213
FutureBase::CompletionCallbackHandle Future<T>::AddOnCompletion(
176214
TypedCompletionCallback callback, void* user_data) const {
177-
return FutureBase::AddOnCompletion(
178-
reinterpret_cast<CompletionCallback>(callback), user_data);
215+
MutexLock lock(mutex_);
216+
if (api_ != nullptr) {
217+
if (callback == nullptr) {
218+
return CompletionCallbackHandle();
219+
}
220+
auto* data =
221+
new detail::TypedCompletionCallbackData<T>{callback, user_data};
222+
return api_->AddCompletionCallback(
223+
handle_, detail::TypedCompletionCallbackTrampoline<T>, data,
224+
detail::DeleteTypedCompletionCallbackData<T>,
225+
/*clear_existing_callbacks=*/false);
226+
}
227+
return CompletionCallbackHandle();
179228
}
180229

181230
#if defined(FIREBASE_USE_STD_FUNCTION)
182231
template <class ResultType>
183232
inline FutureBase::CompletionCallbackHandle Future<ResultType>::AddOnCompletion(
184233
std::function<void(const Future<ResultType>&)> callback) const {
185-
return FutureBase::AddOnCompletion(
186-
*reinterpret_cast<std::function<void(const FutureBase&)>*>(&callback));
234+
if (!callback) {
235+
return CompletionCallbackHandle();
236+
}
237+
return FutureBase::AddOnCompletion([callback](const FutureBase& future) {
238+
callback(static_cast<const Future<ResultType>&>(future));
239+
});
187240
}
188241
#endif // defined(FIREBASE_USE_STD_FUNCTION)
189242

0 commit comments

Comments
 (0)