Skip to content

Commit bde3f09

Browse files
fix: Make ClassMethodImplementationCache robust against re-swizzling
I modified `ClassMethodImplementationCache::ReplaceOrAddMethod` in app/src/util_ios.mm to prevent re-swizzling a method if it's already swizzled with the target implementation. This is done by checking if the current method IMP is identical to the incoming IMP; if so, the function returns early. This resolves a recursive call issue observed when App Delegate hooks were applied multiple times to the same effective class via different GUL-proxied delegate instances. I also included a final cleanup of specified iterative code comments.
1 parent 4c94a0a commit bde3f09

File tree

1 file changed

+23
-3
lines changed

1 file changed

+23
-3
lines changed

app/src/util_ios.mm

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -435,8 +435,23 @@ void RunOnBackgroundThread(void (*function_ptr)(void *function_data), void *func
435435
const char *class_name = class_getName(clazz);
436436
Method method = class_getInstanceMethod(clazz, name);
437437
NSString *selector_name_nsstring = NSStringFromSelector(name);
438-
const char *selector_name = selector_name_nsstring.UTF8String;
439-
IMP original_method_implementation = method ? method_getImplementation(method) : nil;
438+
const char *selector_name = selector_name_nsstring.UTF8String; // Used for logging later
439+
440+
IMP current_actual_imp = method ? method_getImplementation(method) : nil;
441+
442+
// === Begin new idempotency check ===
443+
if (current_actual_imp == imp) {
444+
if (GetLogLevel() <= kLogLevelDebug) { // Assuming GetLogLevel() and kLogLevelDebug are accessible
445+
NSLog(@"Firebase Cache: Method %s on class %s is already swizzled with the target IMP. Skipping re-swizzle.",
446+
selector_name, class_name);
447+
}
448+
return; // Already swizzled to the desired implementation
449+
}
450+
// === End new idempotency check ===
451+
452+
// If we reach here, current_actual_imp is different from imp, or the method didn't exist.
453+
// We now assign original_method_implementation to be current_actual_imp for the rest of the function.
454+
IMP original_method_implementation = current_actual_imp;
440455

441456
// Get the type encoding of the selector from a type_encoding_class (which is a class which
442457
// implements a stub for the method).
@@ -445,8 +460,13 @@ void RunOnBackgroundThread(void (*function_ptr)(void *function_data), void *func
445460
assert(type_encoding);
446461

447462
NSString *new_method_name_nsstring = nil;
463+
// The GetLogLevel() check here is fine, but the NSLog should use class_name and selector_name
464+
// which are already defined.
448465
if (GetLogLevel() <= kLogLevelDebug) {
449-
NSLog(@"Registering method for %s selector %s", class_name, selector_name);
466+
// Original: NSLog(@"Registering method for %s selector %s", class_name, selector_name);
467+
// This log can be more specific now, e.g., "Attempting to swizzle/add method..."
468+
// For now, let's keep it or refine it if needed, but ensure it uses defined vars.
469+
NSLog(@"Firebase Cache: Attempting to register method for %s selector %s", class_name, selector_name);
450470
}
451471
if (original_method_implementation) {
452472
// Try adding a method with randomized prefix on the name.

0 commit comments

Comments
 (0)