logos icon indicating copy to clipboard operation
logos copied to clipboard

%property crashes when no parameters set

Open prolitornandbasturtrumerthydempe opened this issue 5 years ago • 8 comments

The exception is: *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_UITextSizeCache setObject:forKeyedSubscript:]: unrecognized selector sent to instance 0x280aa2fa0'

I am unable to ever modify NSMutableDictionary or NSMutableArray as a property. Can anyone help out?

@interface CHBoardView : UIView
@property NSMutableDictionary *piece;

%hook CHBoardView
%property NSMutableDictionary *piece;

-(void) initializeBoard {
	%orig;
	self.piece = [[NSMutableDictionary alloc] init];
}

// Trying to modify the dict
-(void) moveForward {
    self.piece[@"name"] = @"test";
}

%end

Can you post the relevant stack trace in the crash log?

NSExceptional avatar Nov 18 '20 05:11 NSExceptional

Can you post the relevant stack trace in the crash log?

The stack trace is a bunch of random memory addresses (from Mac Console).

I tried attaching to the process with Xcode but I get: error: Attach failed: "Not allowed to attach to process. Look in the console messages (Console.app), near the debugserver entries when the attached failed. The subsystem that denied the attach permission will likely have logged an informative message about why it was denied.".

error: MachTask::TaskPortForProcessID task_for_pid failed: ::task_for_pid ( target_tport = 0x0203, pid = 39725, &task ) => err = 0x00000005 ((os/kern) failure) error: MachTask::StartExceptionThread (): task invalid, exception thread start failed.

(Even though I can attach without issues with IDA Pro or LLDB CLI, and manually launching debugserver on the device over SSH).

Here's what lldb CLI tells me when I cause the crash (write to the dict):

Process 39693 resuming
Process 39693 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x9c422d6a0)
    frame #0: 0x0000000192e56980 libobjc.A.dylib`objc_retain + 16
libobjc.A.dylib`objc_retain:
->  0x192e56980 <+16>: ldrb   w8, [x8, #0x20]
    0x192e56984 <+20>: tbz    w8, #0x2, 0x192e569a8     ; <+56>
    0x192e56988 <+24>: mov    x8, #0x200000000000
    0x192e5698c <+28>: ldxr   x9, [x0]
Target 0: stopped.

Does it help? Or can you help me get Xcode to attach for the full stack trace?

You should be able to use Cr4shed or Crash Reporter to get a symbolicated crash log. And if you're able to attach a debugger to the process then you should be able to type bt to get a backtrace. Either of those would work but the Cr4shed report is probably better

NSExceptional avatar Nov 18 '20 15:11 NSExceptional

Thanks. Here is the Cr4shed log:

printAnalysis is the function where I add to the dictionary property, which leads to the crash. (The crash happens if the property is NSMutableDictionary, NSMutableArray, or any other object that requires manually alloc'ing. I seem to remember that it doesn't crash if the property is an int (and I try to change the int at some point)).

Date: 18/11/2020, 16:41
Process: Chess
Bundle id: com.chess.iphone
Device: iPhone 7 Plus, iOS 13.6
Bundle version: 3.9.9

Exception type: NSInvalidArgumentException
Reason: -[NSISVariableObservation setObject:forKey:]: unrecognized selector sent to instance 0x2801246a0
Culprit: chesstweaker.dylib

Call stack:
0   CoreFoundation                      0x0000000193119668 0x192fef000 + 0x12a654        // __exceptionPreprocess
1   libobjc.A.dylib                     0x0000000192e3bbcc 0x192e36000 + 0x5bcc          // objc_exception_throw
2   CoreFoundation                      0x000000019301ddd8 0x192fef000 + 0x2edd8         // -[NSOrderedSet initWithSet:copyItems:]
3   CoreFoundation                      0x000000019311d7f8 0x192fef000 + 0x12e7f8        // ___forwarding___
4   CoreFoundation                      0x000000019311f71c 0x192fef000 + 0x13071c        // _CF_forwarding_prep_0
5   chesstweaker.dylib                  0x00000001063f6bfc 0x1063f0000 + 0x6bfc          // _logos_method$_ungrouped$CHBoardView$printAnalysis$output$(CHBoardView*, objc_selector*, objc_object*, CHEngineOutput*)
6   Chess                               0x0000000102816b24 Chess + 3255076
7   Chess                               0x0000000102672184 Chess + 1532292
8   Foundation                          0x0000000193511f78 0x1933db000 + 0x136f78        // __NSThreadPerformPerform
9   CoreFoundation                      0x0000000193097ad8 0x192fef000 + 0xa8ad8         // __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__
10  CoreFoundation                      0x0000000193097a30 0x192fef000 + 0xa8a30         // __CFRunLoopDoSource0
11  CoreFoundation                      0x00000001930971b8 0x192fef000 + 0xa81b8         // __CFRunLoopDoSources0
12  CoreFoundation                      0x00000001930921e8 0x192fef000 + 0xa31e8         // __CFRunLoopRun
13  CoreFoundation                      0x0000000193091ba8 0x192fef000 + 0xa2ba8         // CFRunLoopRunSpecific
14  GraphicsServices                    0x000000019d201344 0x19d1fe000 + 0x3344          // GSEventRunModal
15  UIKitCore                           0x00000001971cd3e4 0x19679f000 + 0xa2e3e4        // UIApplicationMain
16  Chess                               0x00000001025039b4 Chess + 31156
17  libdyld.dylib                       0x0000000192f198f0 0x192f18000 + 0x18f0          // start

{"NSExceptionReason":"-[NSISVariableObservation setObject:forKey:]: unrecognized selector sent to instance 0x2801246a0","ProcessBundleID":"com.chess.iphone","ProcessName":"Chess","Culprit":"chesstweaker.dylib"}

Okay, can you run logos.pl Tweak.xm > Tweak.m and post the contents of Tweak.m? I think Logos is just generating some bad code

(Use a paste service like Ghostbin please)

NSExceptional avatar Nov 19 '20 06:11 NSExceptional

/Users/user/theos/vendor/logos/bin/logos.pl Tweak.xm > Tweak.m
Use of uninitialized value $1 in split at /Users/user/theos/vendor/logos/bin/logos.pl line 604.

And here are lines 603 and a few more from logos.pl:

#check property attribute validity
my @attributes = split/\(?\s*,\s*\)?/, $1;
my $type = $2;
my $name = $3;
my ($assign, $retain, $copy, $nonatomic, $getter, $setter);
my $numattr = 0;

The complete sourcecode of the Tweak.xm (I rewrote the source to include the bare minimum for causing the crash):

@interface CHBoardView : UIView
@property NSMutableDictionary *piece;
@end

%hook CHBoardView
%property NSMutableDictionary *piece;

-(void) initializeChessBoard {
    %orig;
    self.piece = [[NSMutableDictionary alloc] init];
    self.piece[@"abc"] = @"def";
}
%end

edit:

Damn, I'm dumb here. It seems you have to include the property attributes. Changing the line results in no crash: %property (nonatomic, retain) NSMutableDictionary *piece;

The issue seems to be that you aren’t specifying any property attributes. I can’t remember if it’s an intentional design decision to avoid supporting no parameters - even if it is, of course there is still a bug here as it should show a useful error, not a cryptic parsing error.

In your case, the most reasonable value to specify would be (nonatomic, strong).

@interface CHBoardView : UIView
@property (nonatomic, strong) NSMutableDictionary *piece;
@end

%hook CHBoardView
%property (nonatomic, strong) NSMutableDictionary *piece;
…
%end

The default when no parameters are specified to @property is (atomic, assign). With ARC enabled, assign is equivalent to __unsafe_unretained, which means the compiler provides no automatic memory management at all - it’s all up to you. Hence you are reading memory that got deallocated and reused just after Logos’ generated setPiece: method returned. strong however will cause the compiler to add all the necessary memory management instructions.

kirb avatar Nov 19 '20 10:11 kirb

Thanks, that works. I somehow figured it out the moment you posted 👍