gnustep-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Is the GNUstep Objective-C runtime to picky about method signatures?


From: David Chisnall
Subject: Re: Is the GNUstep Objective-C runtime to picky about method signatures?
Date: Tue, 14 Apr 2020 11:34:43 +0100
User-agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:68.0) Gecko/20100101 Thunderbird/68.7.0

On 13/04/2020 15:23, Wolfgang Lux wrote:
I've just recently come across a strange issue where the MySQL interface in the 
SQLClient library had stopped working with a weird error when using the 
libobjc2 runtime. In particular, the code was complaining that the 
backendQuery:recordType:listType: method was called without a loaded bundle. A 
debugging session later it was clear that the MySQL backend bundle was actually 
loaded into the program and that the backendQuery:recordType:listType: was 
available inside the bundle, but that the runtime simply refused to call the 
override and just called the implementation in the SQLClient base class 
instead, which emits the error message.
A more careful look at the code revealed a subtle difference between the 
definition of the backendQuery:recordType:listType: method in the SQLClient 
class and its MySQL bundle subclass: While the former (and all other backend 
bundles) uses id parameters for the record and list type arguments, the MySQL 
bundle was using Class parameters instead. This resulted in slightly different 
method signatures (@40@0:8@16@32 vs. @40@0:8#16#32 on a 64-bit architecture) 
and the libobjc2 method dispatch apparently is rather picky about those 
signatures. As I've already changed the SQLClient library to use consistent 
types, I've condensed the issue into a little test program (Test1.m) below. The 
output for this on macOS with Apple's Foundation looks like this (and for 
GNUstep with gcc and the gcc runtime it looks similar):

Calling a method with the wrong signature is undefined behaviour in Objective-C. The Apple runtime just ignores the type entirely and will happily corrupt your stack in a few cases. We try to allow it in benign cases, which probably should include `Class` vs `id`, though I'm not entirely convinced: it's fine to pass a `Class` to something that expects an `id`, but passing an arbitrary object to something that expects a `Class` can cause exciting breakage.

And while I was writing that test program, I accidentally uncovered another bug 
in the libobjc2 runtime (see Test2.m): When calling super with a method that 
isn't implemented by the super class (or its own ancestors) libobjc2 simply 
does nothing, as if the method was called against nil.

This is a bug.  Please open an issue on GitHub so that I can track it.

David



reply via email to

[Prev in Thread] Current Thread [Next in Thread]