Crash EXC_BAD_ACCESS on string with format - ios

I am processing raw IP data to process a video signal (ATSC-MH). However, I am having issues with some basic issue and I'm apparently fried at the moment and need another set of eyes.
This is the function that flips. Funny part is that it was working for a while and I can't rememeber what I changes. The line that is **d is the one that is referred to in the error log. I can't do much NSLog debugging because the stream comes from an accessory(so no direct debugging pipe :().
-(NSString*)reportSMT{
//NSString* ret = #"Not implemented yet";
__autoreleasing NSMutableString* ret = [[NSMutableString alloc] initWithFormat:#"\nSMT:\n SecSynInd:%# PriInd:%#\n SecLen:%d SMTMHProVer:%d\n EnID:%d VerNum:%d\n CurNxtInd:%# SecNum:%d\n lastSec#:%d #Servs:%d\n\n",(Header.section_syntax_indicator?#"YES":#"NO"),(Header.private_indicator?#"YES":#"NO"),Header.section_length,Header.SMT_MH_protocol_version,Header.ensemble_id,Header.version_number,(Header.current_next_indicator?#"YES":#"NO"), Header.section_number,Header.last_section_number,Header.num_MH_services];
[ret appendString:[NSString stringWithFormat:#"SMT Table:\n"]];
for (int i = 0; i<Header.num_MH_services; i++) {
**[ret appendString:[NSString stringWithFormat:#"Serv(%d):\n ServID:%d MultiEnServ:%d\n ServStat:%d ServSPInd:%#\n ServShotName:%#\n ServCat:%d\n source:%# dest:%#\n #MHServComps:%d\n",i,Services[i].MH_service_id,Services[i].multi_ensemble_service,Services[i].MH_service_status,(Services[i].SP_indicator?#"YES":#"NO"),[NSString stringWithUTF8String:(char*)Services[i].short_MH_service_name],(Services[i].service_source_IP_address_flag?[Utility ParseIP:Services[i].service_source_IP_address]:#"N/A"),(Services[i].service_destination_IP_address_flag?[Utility ParseIP:Services[i].service_destination_IP_address]:#"N/A"),Services[i].num_components]];**
for (int m=0; m<Services[i].num_components; m++) {
[ret appendString:[NSString stringWithFormat:#" Comp(%d)(essential:%#):\n port#count:%d compSource:%#\n compDest:%# destPort:%d\n",m,(Services[i].components[m].essential_component_indicator?#"YES":#"NO") ,Services[i].components[m].port_num_count,(Services[i].components[m].component_source_IP_address_flag?[Utility ParseIP:Services[i].components[m].component_source_IP_address]:#"N/A"),(Services[i].components[m].component_destination_IP_address_flag?[Utility ParseIP:Services[i].components[m].component_destination_IP_address]:#"N/A"),Services[i].components[m].component_destination_UDP_port_num]];
}
}
return [ret copy];
}
Here is that Utility parseIP function. Though it didn't change anything to comment the call to it and hardcode a value there:
+(NSString*)ParseIP:(long)ip{
__autoreleasing NSString* ret = nil;
if (ip) {
unsigned char* ipPtr = (unsigned char*)&ip;
unsigned char ipc[4];
for (int i=0; i<4; i++) {
ipc[i] = *(ipPtr+i);
}
ret = [NSString stringWithFormat:#"(%d.%d.%d.%d)",ipc[3],ipc[2],ipc[1],ipc[0]];
}
return ret;
}
Here is the structure for that part of the SMT:
struct SMTChunk{
unsigned int MH_service_id;//16
unsigned char multi_ensemble_service;//2
unsigned char MH_service_status;//2
bool SP_indicator;//1
unsigned char short_MH_service_name_length;//3 /* m */
unsigned char* short_MH_service_name;//16*m
unsigned char reserved2;//2 should be 11
unsigned char MH_service_category;//6
unsigned char num_components;//5
bool IP_version_flag;//1
bool service_source_IP_address_flag;//1
bool service_destination_IP_address_flag;//1
unsigned long service_source_IP_address;//32 if (service_source_IP_address_flag)
unsigned long service_destination_IP_address;//32 if (service_destination _IP_address_flag)
struct SMTComponent* components;
unsigned char reserved4;//4 1111(f)
unsigned char num_MH_service_level_descriptors;//4
struct SMTServiceDescriptor* descriptors;
};
Like I said this was working before, so I'm pretty sure the parser that fills the data structure is fine.
Device Log(important part):
Date/Time: 2012-03-06 00:56:40.480 -0600
OS Version: iPhone OS 5.0.1 (9A405)
Report Version: 104
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x0000000a
Crashed Thread: 0
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libobjc.A.dylib 0x300e4fb6 objc_msgSend + 10
1 Foundation 0x30dd9d14 _NSDescriptionWithLocaleFunc + 44
2 CoreFoundation 0x335d699e __CFStringAppendFormatCore + 7998
3 CoreFoundation 0x33551210 _CFStringCreateWithFormatAndArgumentsAux + 68
4 Foundation 0x30dd9c3e +[NSString stringWithFormat:] + 54
5 APT-test 0x000c9630 -[SMT reportSMT] (SMT.m:178)
6 APT-test 0x000c54bc -[VideoViewController saveTimerFun:] (VideoViewController.mm:940)
7 Foundation 0x30e79616 __NSFireTimer + 138
It feels like I've been working on this app forever so any help or pointers you can give are welcome.
Thanks in advance!

The printf wildcards and arguments do not appear to be balanced properly:
[NSString stringWithFormat:#"1%d 2%d 3%d 4%d 5%# 6%# 7%d 8%# 9%# A%d",
/* 1 */i,
/* 2 */Services[i].MH_service_id,
/* 3 */Services[i].multi_ensemble_service,
/* 4 */Services[i].MH_service_status,
/* 5 */(Services[i].SP_indicator?#"YES":#"NO"),
/* 6 */[NSString stringWithUTF8String:(char*)Services[i].short_MH_service_name],
/* 7 */(Services[i].service_source_IP_address_flag?[Utility ParseIP:Services[i].service_source_IP_address]:#"N/A"),
/* 8 */(Services[i].service_destination_IP_address_flag?[Utility ParseIP:Services[i].service_destination_IP_address]:#"N/A"),
/* 9 */Services[i].num_components]];
It looks like you’re trying to match the %# specifier at position 9 with Services[i].num_components, which is quite probable to result in EXC_BAD_ACCESS. You would do best to rewrite the code so that it’s more readable, this mess is only asking for trouble.

Related

backtrace miss the function that caused a crash

I use backtrace and backtrace_symbols to collect the call stack when my app crashed.
void InstallSignalHandler(void)
{
signal(SIGHUP, SignalExceptionHandler);
signal(SIGINT, SignalExceptionHandler);
signal(SIGQUIT, SignalExceptionHandler);
signal(SIGABRT, SignalExceptionHandler);
signal(SIGILL, SignalExceptionHandler);
signal(SIGSEGV, SignalExceptionHandler);
signal(SIGFPE, SignalExceptionHandler);
signal(SIGBUS, SignalExceptionHandler);
signal(SIGPIPE, SignalExceptionHandler);
}
void SignalExceptionHandler(int signal)
{
NSMutableString *mstr = [[NSMutableString alloc] init];
[mstr appendString:#"Stack:\n"];
void* callstack[128];
int i, frames = backtrace(callstack, 128);
char** strs = backtrace_symbols(callstack, frames);
for (i = 0; i <frames; ++i) {
[mstr appendFormat:#"%s\n", strs[i]];
}
NSLog(#"%#", mstr);
free(strs);
}
When I check the log in console, I just find the log miss the function that caused the crash.The function is:
+ (void)testCrash
{
int *nullPointer = NULL;
*nullPointer = 2019;
}
And the log in console is:
0 TestApp 0x0000000101d1e040 SignalExceptionHandler + 160
1 libsystem_platform.dylib 0x000000011002bb5d _sigtramp + 29
2 ??? 0x0000000000000000 0x0 + 0
3 TestApp 0x00000001019bbc6f __39+[MyCrashTesting showInViewController:]_block_invoke + 303
4 UIKit 0x000000010b09a559 -[UIAlertController _invokeHandlersForAction:] + 105
5 UIKit 0x000000010b09af5e __103-[UIAlertController _dismissAnimated:triggeringAction:triggeredByPopoverDimmingView:dismissCompletion:]_block_invoke.461 + 16
6 UIKit 0x000000010ae42ca2 -[UIPresentationController transitionDidFinish:] + 1346
7 UIKit 0x000000010ae46b12 __56-[UIPresentationController runTransitionForCurrentState]_block_invoke.436 + 183
8 UIKit 0x000000010ba2a3b4 -[_UIViewControllerTransitionContext c
I have thought the function name "testCrash" should be in the top of the log. Does I do something wrong?
Since this is a very simple method with no arguments and no ARC heavylifting inside clang the Objective-C compiler is able to do an optimization (-O1 is enough to achieve that) of removing the message runtime call.
You can prevent this behavior with:
+ (void)testCrash __attribute__((optnone))
{
int *nullPointer = NULL;
*nullPointer = 2019;
}
The lesson learnt here is you should never rely on particular stacktrace to achieve something during your program execution. Diagnostics is fine as long as you understand the optimizing principles you've just encountered.

Getting IPV4 address as a String

Im using Bonjour to browse for available services from specific devices. I can successfully obtain and resolve the services returned from the browse, however I would like to take the service and retrieve it's IPV4 address in String form. To do this I am using the arpa/inet library to translate the NSdata object received by the NSNetService.addresses into a String. The code below works most of the time however occasionally the line below results in the crashing of the app.
NSString *ipString = [NSString stringWithFormat: #"%s",
inet_ntoa(socketAddress->sin_addr)];
The error: EXC_BAD_ACCESS
I am sure it has to do with the way I have declared this code, any ideas?
+ (NSString *)getStringFromAddressData:(NSData *)dataIn {
struct sockaddr_in *socketAddress = nil;
socketAddress = (struct sockaddr_in *)[dataIn bytes];
NSString *ipString = [NSString stringWithFormat: #"%s", inet_ntoa(socketAddress->sin_addr)];
return ipString;
}
Stack trace:
2015-08-13 08:23:45.860 Semiphores[4664:2119558] Stack trace : (
0 Semiphores 0x0000000100001c0b +[BonjourAddressHelper getStringFromAddressData:] + 107
1 Semiphores 0x0000000100007c8a _TFFC10Semiphores17BonjourController15resolveServicesFS0_FPSs9AnyObject_T_U_FT_T_ + 2682
2 Semiphores 0x0000000100007207 _TTRXFo__dT__XFdCb__dT__ + 39
3 libdispatch.dylib 0x00000001006852bb _dispatch_call_block_and_release + 12
4 libdispatch.dylib 0x000000010067fd43 _dispatch_client_callout + 8
5 libdispatch.dylib 0x0000000100683283 _dispatch_root_queue_drain + 1471
6 libdispatch.dylib 0x0000000100694cd0 _dispatch_worker_thread3 + 106
7 libsystem_pthread.dylib 0x00007fff86770637 _pthread_wqthread + 729
8 libsystem_pthread.dylib 0x00007fff8676e40d start_wqthread + 13
)
What would happen if someone passed in nil data?
+ (NSString *)getStringFromAddressData:(NSData *)dataIn {
if (dataIn != nil) {
struct sockaddr_in *socketAddress = nil;
socketAddress = (struct sockaddr_in *)[dataIn bytes];
NSString *ipString = [NSString stringWithFormat: #"%s", inet_ntoa(socketAddress->sin_addr)];
return ipString;
}
return #"";
}

convert MH_EXECUTE to MH_DYLIB (mach-o)

The problem:
I have 2 MH_EXECUTE iOS binary files (compiled, no source code).
Lets name them binary1 and binary2.
I try to switch between them before UIApplicationMain is called!
1 try
I successfully do this with binary1 and one dylib. So I try to convert MH_EXECUTE to MH_DYLIB.
step 1
creating iOS Application binary1
#import <dlfcn.h>
int main(int argc, char * argv[])
{
NSLog(#"binary1 -> Hello, World!");
void *handle = dlopen([[[NSBundle mainBundle] pathForResource:#"binary2" ofType:nil] cStringUsingEncoding:NSUTF8StringEncoding], RTLD_NOW);
if (handle)
{
NSLog(#"DLOPEN is OK!");
}
else
{
NSLog(#"!OK ... --> %s", dlerror());
}
return 0;
}
creating iOS Application binary2
int main(int argc, char * argv[])
{
NSLog(#"binary2 -> Hello, World!");
return 0;
}
When I run binary1 I get:
step 2
Lets see the difference MH_EXECUTE vs MH_DYLIB
fullscreen
as we can see the main difference here is File Type: MH_EXECUTE vs MH_DYLIB
Lets change them and run binary1 again.
After change the result was out of address space
step 3
Lets see Load Commands
fullscreen
* in dylib there is NO __PAGEZERO segment
* dylib __TEXT segment VM address == 0 but in binary2 == 0000000100000000
So lets patch them too ... (patched: __TEXT, ___DATA and __LINKEDIT)
After run binary1 i get malformed mach-o image: segment __PAGEZERO overlaps load commands
step 4
I successfully removed __PAGEZERO from Load Commands now binary looks like dylib:
fullscreen
But on start binary1 I get BAD_ACCESS
Exception Type: EXC_BAD_ACCESS (SIGBUS)
Exception Subtype: KERN_PROTECTION_FAILURE at 0x00000001019e0010
Triggered by Thread: 0
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 dyld 0x0000000120016d78 ImageLoaderMachOCompressed::rebase(ImageLoader::LinkContext const&) + 892
1 dyld 0x0000000120016c24 ImageLoaderMachOCompressed::rebase(ImageLoader::LinkContext const&) + 552
2 dyld 0x0000000120010c8c ImageLoader::recursiveRebase(ImageLoader::LinkContext const&) + 132
3 dyld 0x000000012001039c ImageLoader::link(ImageLoader::LinkContext const&, bool, bool, bool, ImageLoader::RPathChain const&) + 176
4 dyld 0x00000001200088e0 dyld::link(ImageLoader*, bool, bool, ImageLoader::RPathChain const&) + 180
5 dyld 0x000000012000df68 dlopen + 684
6 libdyld.dylib 0x0000000194e65b94 dlopen + 68
7 binary1 0x00000001000b7e18 main (main.m:16)
8 libdyld.dylib 0x0000000194e66a04 start + 0
Any idea ???
You're getting BAD_ACCESS because you removed __PAGEZERO and thus invalidated the rebasing opcodes. Keep __PAGEZERO but nullify it. I similarly converted an executable into a shared library and it's loading fine on iOS and macOS.

Why my [UIScrollView removeFromSuperview] is crashing?

The crash log is below.
Do you know any particular reason why might [UIScrollView removeFromSuperview] can crash? The scrollview contains view hierarchy with different types of UIViews. I also finds that the ad hoc version crash often not the debug version. I could not find any reason for that.
Same viewcontroller is loaded in a different flow in iPhone that works fine. But in iPad it crashes.
In iPad, in a container view controller, only viewcontroler.view is loaded.
Incident Identifier: EE102239-34D1-4BE7-8B52-41F74AB26203
CrashReporter Key: 2b11ea2a01ac5618e199ffc5a1e1f321600bb6a9
Hardware Model: iPad3,4
Version: ??? (???)
Code Type: ARM (Native)
Parent Process: launchd [1]
Date/Time: 2013-06-18 15:19:16.132 +0200
OS Version: iOS 6.1.3 (10B329)
Report Version: 104
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x00000000
Crashed Thread: 0
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libobjc.A.dylib 0x3bab7070 prepareForMethodLookup + 20
1 libobjc.A.dylib 0x3bab6fb2 lookUpMethod + 42
2 libobjc.A.dylib 0x3bab6f7e _class_lookupMethodAndLoadCache3 + 14
3 libobjc.A.dylib 0x3bab6638 objc_msgSend_uncached + 24
4 QuartzCore 0x357f2a72 CA::Layer::contents_visibility_changed(CA::Transaction*, bool) + 50
5 QuartzCore 0x357f29de CA::Layer::mark_visible(CA::Transaction*, bool) + 190
6 QuartzCore 0x357f29b2 CA::Layer::mark_visible(CA::Transaction*, bool) + 146
7 QuartzCore 0x357f29b2 CA::Layer::mark_visible(CA::Transaction*, bool) + 146
8 QuartzCore 0x357f29b2 CA::Layer::mark_visible(CA::Transaction*, bool) + 146
9 QuartzCore 0x357f29b2 CA::Layer::mark_visible(CA::Transaction*, bool) + 146
10 QuartzCore 0x357f28d2 CA::Layer::update_removed_sublayer(CA::Transaction*, unsigned int) + 18
11 QuartzCore 0x357f255a CA::Layer::remove_sublayer(CA::Transaction*, CALayer*) + 130
12 QuartzCore 0x357f246a CA::Layer::remove_from_superlayer() + 34
13 UIKit 0x35a6e92c -[UIView(Hierarchy) removeFromSuperview] + 144
14 UIKit 0x35b857bc -[UIScrollView removeFromSuperview] + 60
15 MyApp 0x000bde8a -[iPadNavigationController vcAnimationDone] (iPadNavigationController.m:400)
16 UIKit 0x35a55ab6 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 154
17 UIKit 0x35aca8f8 -[UIViewAnimationState animationDidStop:finished:] + 44
18 QuartzCore 0x35801304 CA::Layer::run_animation_callbacks(void*) + 204
19 libdispatch.dylib 0x3bed55d8 _dispatch_client_callout + 20
20 libdispatch.dylib 0x3bed8e40 _dispatch_main_queue_callback_4CF + 224
21 CoreFoundation 0x33c051ac __CFRunLoopRun + 1284
22 CoreFoundation 0x33b78238 CFRunLoopRunSpecific + 352
23 CoreFoundation 0x33b780c4 CFRunLoopRunInMode + 100
24 GraphicsServices 0x37733336 GSEventRunModal + 70
25 UIKit 0x35a942b4 UIApplicationMain + 1116
A few line from the code (as asked),
previous = showing;
showing = [ vc retain ];
showing.view.frame = startFrameIn;
[ container addSubview:showing.view ];
CGContextRef context = UIGraphicsGetCurrentContext();
[ UIView beginAnimations:nil context:context ];
[ UIView setAnimationDelegate:self ];
[ UIView setAnimationDidStopSelector:#selector(vcAnimationDone) ];
[ UIView setAnimationCurve:UIViewAnimationCurveEaseOut ];
[ UIView setAnimationDuration:0.4 ];
previous.view.frame = endFrameOut;
showing.view.frame = detailFrame;
[ UIView commitAnimations ];
}
- (void) vcAnimationDone {
if ( previous != nil ) {
if (previous.view.superview != nil) {
[previous.view removeFromSuperview];
}
[ previous release ];
previous = nil;
}
A very probable reason is that you are overreleasing your scrollview or one of the views inside it.
Calling removeFromSuperview then deallocates the view instead of simply decreasing the retain count.
Actually, if you are still stuck with non-ARC project, Static Code Analysis is very useful for this kind of bug. Retain/release balancing issues are hard to pin down, and nearly impossible with incomplete method so I suggest you post the full method body if possible.
Thanks everyone for your answers, tips and tricks. However one thing I want share with you is the cause of the crash. I found that the crash was at different thread in different times. I had several views loaded with button pressing/menu in my iPad app. Some of the button pressing fetch data from web service. So I was bit confused to get the cuase of crash, animation, or url connection etc... I tried with enabled NSZombie objects, but it did not show any information.
Then I tried with Guard Malloc. This only runs in Simulator. And magically I found the code point of crash. I have function to convert a hex string into data. There I have line of code to make a C string null terminated. where I assigned 0 at the last index. and that makes the crash!
tmpCh[count] = 0;
I do not why, but probably it takes some time in the memory management procedure in iOS so it crash at different thread at different times. But with Guard malloc in Simulator, it always point out here and when I rewrite the code, the crash is gone.
/* Converts a hex string to bytes.
Precondition:
. The hex string can be separated by space or not.
. the string length without space or 0x, must be even. 2 symbols for one byte/char
. sample input: 23 3A F1 OR 233AF1
*/
+ (NSData *) dataFromHexString:(NSString*)hexString
{
if (hexString.length < 1) {
return nil;
}
char * tmpCh = (char *) malloc([hexString length] * sizeof(char));
int count = 0;
for (int k=0; k<hexString.length;k++) {
char c = [hexString characterAtIndex:k];
if (c == (char)0x20) { //skip space
continue;
}
if (c == '0') { // skip 0x
if(k+1 < hexString.length){
if ([hexString characterAtIndex:k+1] == 'x'
|| [hexString characterAtIndex:k+1] == 'X' )
{
k = k + 1;
continue;
}
}
}
tmpCh[count] = c;
count++;
}
tmpCh[count] = 0; // make null terminated string
if (count % 2) {
return nil;
}
NSString *temp = [[NSString alloc] initWithUTF8String:tmpCh];
free(tmpCh);
if ([temp length] % 2 != 0) {
return nil;
}
NSMutableData *result = [[NSMutableData alloc] init];
unsigned char byte;
char hexChars[3] = {0};
for (int i=0; i < (temp.length/2); i++) {
hexChars[0] = [temp characterAtIndex:i*2];
hexChars[1] = [temp characterAtIndex:i*2+1];
if (![Util isValidChar:hexChars[0]] || ![Util isValidChar:hexChars[1]]) {
return nil;
}
byte = strtol(hexChars, NULL, 16);
[result appendBytes:&byte length:1];
}
NSData * data = [NSData dataWithData:result];
[result release];
return data;
}

ios Right way to free 2 dimensional memory allocated via calloc

I have a iOS app. I allocate 2d memory and then deallocate using free function. Is this the right way to free? Recently I had crash pointing to free statement. Should I be releasing buf[i] in loop?
+(int**) initArr:(int) Nr:( int) Nc
{
int ** buf;
buf = calloc(Nr,sizeof(int*));
for(int i = 0; i < Nr; i++)
{
buf[i] = calloc(Nc,sizeof(int));
}
//Funny Processing
//Release
for(int i = 0; i < Nr; i++)
free(buf[i]);
free(buf);
}
Here is the error message
2 libsystem_c.dylib 0x328b87ec _sigtramp + 48
3 libsystem_c.dylib 0x328ae20e pthread_kill + 54
4 libsystem_c.dylib 0x328a729e abort + 94
5 libsystem_c.dylib 0x32862380 free + 380
6 MyApp 0x0009be52 +[clsGlobalHelper resizeImageAvg:::] (clsGlobalHelper.m:300)

Resources