0
votes

Currently I am working on an Objective-c / Cocoa app that finds images in other documents. However I am having an issue with the NSData I am analysing since after some time the NSData becomes null. Below is the code to create the NSData, get the length and some basic debugging.

/* Get Data */
NSError *error;
NSData *data = [NSData dataWithContentsOfFile:file options:NSDataReadingMapped error:&error];

/* Split Data into hex chunks */
/* Get length of data */
NSUInteger data_length = [data length];

/* Debug NSLogs */
NSLog(@"[1] Data length: %lu",(unsigned long)data_length);
NSLog(@"[1] Data: %@ with Error: %@",data,error);

When I NSLog the data here the document that was passed is written to the console in its hex representation.

However, when I try to process the data the debug NSLog at the end says the data is null. (The for loop checks the data for the hex FF) The code is below:

/* Declare start and end pointer */
NSUInteger start_point = data_length + 2;
NSUInteger end_pointer = data_length + 2;

/* loop through data */
for (NSUInteger i = 0; i < data_length; i++) {
    // Create Range
    NSRange range = NSMakeRange(i, (i+1));
    // Allocate Byte
    Byte byte[1];
    // Get data from data set
    [data getBytes:byte range:range];
    // Convert Byte (char representation) to NSData
    NSData *byte_data = [NSData dataWithBytes:byte length:1];
    // Set string representation of temp_data
    NSString *byte_check = [NSString stringWithFormat:@"%@",byte_data];
    // Check Byte
    if ([byte_check isEqualToString:@"<FF>"]) {
        // First byte found, check if next is correct
        NSRange range2 = NSMakeRange((i+1), (i+2));
        Byte byte2[1];
        [data getBytes:byte2 range:range2];
        NSData *byte_data2 = [NSData dataWithBytes:byte2 length:1];
        NSString *byte_check2 = [NSString stringWithFormat:@"%@",byte_data2];
        if ([byte_check2 isEqualToString:@"<E0>"]) {
            // Success found start of JPEG
            start_point = i;
            // set i to length + 1 to stop loop
            i = data_length + 1;
        }
    }
}

/* Debug point */
NSLog(@"pointer: %lu length: %lu",(unsigned long)end_pointer, (unsigned long)data_length);
NSLog(@"[2] DATA BYTES: %@ with Error: %@",data,error);

In the second part the length of the NSData also becomes 0.

Below is the NSLog output, I have shortened the hex output in order to not make it too long.

2015-09-10 21:11:24.935 PicRecover[51550:13961579] [1] Data length: 66528
2015-09-10 21:11:24.939 PicRecover[51550:13961579] [1] Data: <504b0304 ...
... 01000000> with Error: (null)
2015-09-10 21:11:24.960 PicRecover[51550:13961579] pointer: 0 length: 0
2015-09-10 21:11:24.960 PicRecover[51550:13961579] [2] DATA BYTES: (null) with Error: (null)

I hope someone understands the NSData more than I do and can point out my mistake. If you need any more information I can always add it.

Thank you very much in advance.

2
It will only 'become null' if NULL was assigned. Thus NULL was assigned. Find out why and fix the usage/assumption.user2864740
Well as you can probably see from my code I'm not assigning null. Do you have any idea how and or why its being assigned?jniegsch
Again, Thus NULL was assigned (either that or you are stomping the stack, which is unlikely, or the result is being misinterpreted). So then, where do the assignments occur and when can they return NULL? Could there be a case when it is never assigned a value?user2864740

2 Answers

1
votes

NSMakeRange takes an offset and a length, you are passing two offsets... This means your ranges are a lot larger than you think and you are writing all over memory, given your destination buffer is just one byte long.

Also your check for a specific byte value is over complicated and unreliable as it uses the result of the description method (it's called when you do the stringWithFormat: call). You can just compare your byte value directly, as with any other integral type, e.g.:

if (byte[0] == 0xFF) ...

Finally look up what the break statement does.

HTH

0
votes

To add to @CRD's answer, you should look into memmem & other existing functions.

Also: Instead of copying the NSData content to an external buffer, you can access the internal buffer directly using CFDataGetBytePtr or NSMutableData -mutableBytes.

For the NSMakeRange issue — C allows you to overwrite arbitrary memory. You've only allocated one byte for the byte variable, but you're writing i + 1 bytes to that memory location.

That means you're writing over whatever information was right next to byte in memory.

That could absolutely include the contents of your data pointer.