Blocks appear to have incorrect type encodings, according to the Objective-C runtime

Issue #182 resolved
Max Bélanger
created an issue

We've noticed, while testing with a block-heavy API (i.e lots XPC usage), that errors can occur if the third-party API inspects (through NSMethodSignature) the signature of a block. Signatures appear to translate every type encoding to @ rather than the correct value.

When PyObjCBlock_Create is called, it does not appear to ever call block_signature to infer the actual signature. Rather, it seems to rely on what was created through parsing the metadata in setup_descr/process_metadata_dict, which appears to make up a signature with a matching number of parameters (e.g. a regular block with a single parameter becomes @@@). This means the following error appears when trying to use XPC (consuming):

[NSXPCConnection sendInvocation]: Return value of block argument must be 'void'.

This likely works for most cases where the values are indeed pointer-sized, but this breaks when inspection happens.

Comments (5)

  1. Max Bélanger reporter

    We've found a "workaround", and although everything works, this is likely incorrect:

    diff --git a/pyobjc-core/Modules/objc/block_support.m b/pyobjc-core/Modules/objc/block_support.m
    --- a/pyobjc-core/Modules/objc/block_support.m
    +++ b/pyobjc-core/Modules/objc/block_support.m
    @@ -372,13 +372,13 @@
         *block = gLiteralTemplate;
         block->descriptor = (struct block_descriptor*)(((char*)block) + sizeof(struct block_literal));
         *(block->descriptor) = *(gLiteralTemplate.descriptor);
    -    if (signature->signature == NULL) {
    +    //if (signature->signature == NULL) {
             signature->signature = block_signature(signature);
             if (signature->signature == NULL) {
                 return NULL;
    -    }
    +    //}
         block->descriptor->signature = signature->signature;
         block->flags |= BLOCK_HAS_SIGNATURE;
         block->isa = gStackBlockClass;
  2. Log in to comment