Skip to content

Invalid offset calculation for some ivars #113

@xavierjurado

Description

@xavierjurado

Runtime is not able to calculate the correct ivar offsets under some specific circumstances. Take a look at the following example:

import Foundation
import Runtime

class IncorrectLayout: NSObject {
  let ivar1 = AttributedString("ivar1") // Value type
  let ivar2 = NSDate()                  // Reference type
}

Inspecting this type through Runtime gives the following offsets:

PropertyInfo(name: "ivar1", type: Foundation.AttributedString, isVar: false, offset: 0, ownerType: ...)
PropertyInfo(name: "ivar2", type: NSDate, isVar: false, offset: 8, ownerType: ...)

But that's not correct as far as I understand. According to ivar_getOffset the offsets are off by 8 bytes. Because of that, using get(from:) will return an instance pointing to an invalid memory address, resulting in a crash when invoking any method on it. Eg:

let instance = IncorrectLayout()
let info = try typeInfo(of: IncorrectLayout.self)

try info.properties.forEach { property in
  if property.name == "ivar2" {
    let ivar = try property.get(from: instance) as NSDate
    print(ivar.timeIntervalSinceNow) // Unrecognized selector -[_TtCV10Foundation16AttributedString4Guts timeIntervalSinceNow]!
  }
}

Additional notes

Attempting to change almost anything from IncorrectLayout will likely fix the issue. Eg:

  • Removing the NSObject superclass
  • Changing the type of ivar1 to a reference type
  • Removing ivar1

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions