Skip to content

Wrong lookup behavior in super trampoline when subclasses override below injection #21

Open
@lukaskubanek

Description

@lukaskubanek

Originally pointed out in this discussion. When installing the super trampoline into a class hierarchy, if a subclass below the injection point overrides the method, the lookup logic in ITKReturnThreadSuper(…) misroutes to the nearest override, potentially causing infinite recursion.

Reproduction

import ITKSuperBuilder
import XCTest

final class TrampolineTests: XCTestCase {
    func testTrampolineEdgeCase() throws {
        // Inject our super trampoline into `Level2` for `sayHello()`.
        try ITKSuperBuilder.addSuperInstanceMethod(
            to: Level2.self,
            selector: #selector(Level2.sayHello)
        )
        
        // Create a `Level4` instance and call `sayHello()`. We expect this to eventually
        // call `Level1`’s implementation exactly once. However, due to the broken lookup
        // logic in `ITKReturnThreadSuper(…)`, it will loop forever between Level3 overrides.
        let object = Level4()
        object.sayHello()
    }
}

class Level1: NSObject {
    @objc dynamic func sayHello() {
        print("Level1 says hello")
    }
}

class Level2: Level1 {
    // No override here. This is where we install the trampoline.
}

class Level3: Level2 {
    @objc dynamic override func sayHello() {
        print("Level3 says hello")
        super.sayHello()
    }
}

class Level4: Level3 {
    @objc dynamic override func sayHello() {
        print("Level4 says hello")
        super.sayHello()
    }
}

Expected output:

Level4 says hello
Level3 says hello
Level1 says hello

Actual output:

Level4 says hello
Level3 says hello
Level3 says hello
Level3 says hello
… (infinite repetition)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions