0

I have a method that contains a few conditionals. The first conditional works fine and does not cause any problems. However, the second one causes the app to crash.

- (void)didReceiveGaiaGattResponse:(CSRGaiaGattCommand *)command
{
    GaiaCommandType cmdType = [command getCommandId];
    NSData *requestPayload = [command getPayload];
    uint8_t success = 0;

    NSLog(@"cmdType: %li", (long)cmdType);
    [requestPayload getBytes:&success range:NSMakeRange(0, sizeof(uint8_t))];

    if (cmdType == GaiaCommand_GetCurrentBatteryLevel && requestPayload.length > 1)
    {
        uint16_t value = 0;
        [requestPayload getBytes:&value range:NSMakeRange(1, sizeof(uint16_t))];
        NSInteger battery = CFSwapInt16BigToHost(value);

        [self sendEventWithName:someDEVICE_BATTERY_CHANGED body:@{@"batteryLevel":[NSNumber numberWithInteger:battery]}];
        return;
    }
     else if (cmdType == GaiaCommand_GET_FBC && requestPayload.length > 1)
    {
         uint16_t value = 0;
         [requestPayload getBytes:&value range:NSMakeRange(1, sizeof(uint16_t))];
         NSInteger feedbackCancellationMode = CFSwapInt16BigToHost(value);
         [self sendEventWithName:FEEDBACK_CANCELLATION_MODE body:@{@"feedbackCancellationMode": [NSNumber numberWithInt:feedbackCancellationMode]}];
         return;
    }

    //do more stuff
}

The conditional

if (cmdType == GaiaCommand_GetCurrentBatteryLevel && requestPayload.length > 1)

works without problems.

However, the conditional

else if (cmdType == GaiaCommand_GET_FBC && requestPayload.length > 1)

causes the following warning in xcode

Implicit conversion loses integer precision: 'NSInteger' (aka 'long') to 'int'

In addition, I also saw the error message in the debugger

* Terminating app due to uncaught exception 'NSRangeException', reason: '* -[_NSInlineData getBytes:range:]: range {1, 2} exceeds

data length 2'

VK1
  • 1,676
  • 4
  • 28
  • 51

2 Answers2

1

Consider what this is telling you:

Terminating app due to uncaught exception 'NSRangeException', reason:
'-[_NSInlineData getBytes:range:]: range {1, 2} exceeds data length 2'

Your data object is 2 bytes in length. The first byte, at position 0, is (according to your code) the success value. That leaves one more byte at position 1 to handle. But your code is attempt to copy 2 bytes out of it — that's the range {1, 2} in the message; a range starting at position 1 and with a length of 2. You're reading past the end of the data.

You have to check that the data has enough data to satisfy the -getBytes:... call you're attempting to make. You may also need to correct your assumptions about how large the cancellation mode value in the buffer is supposed to be, because it's apparently smaller than you expect. Your code assumes it's a uint16_t (2 bytes) but there's only one byte left in the data.

Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
  • The cancellation mode should return either 0 or 1. Or maybe it will return either 00 or a 01. I'm not sure how to adjust the code to accordingly. I'm very new/unfamiliar to Objective C and native modules in general(I usually just work with React Native. – VK1 Jun 12 '19 at 05:35
  • 1
    Knowing that it's either 0 or 1 isn't enough. You need to know the layout of the data you're receiving. Where is each value in the data buffer and how many bytes long are they? If the cancellation mode is expected to be just one byte, change the type of `value` in that branch to `uint8_t` and change the place where you have `sizeof(uint16_t)` to `sizeof(value)`. And remove the call to `CFSwapInt16BigToHost()`; just assign `value` to `feedbackCancellationMode`. – Ken Thomases Jun 12 '19 at 15:09
  • That was exactly what I needed! Thanks a bunch! – VK1 Jun 13 '19 at 01:54
0
[NSNumber numberWithInt:feedbackCancellationMode]}]

should be

[NSNumber numberWithInteger: feedbackCancellationMode]}]
VK1
  • 1,676
  • 4
  • 28
  • 51