-
Notifications
You must be signed in to change notification settings - Fork 26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Encoder: handle invalid types gracefully #592
Conversation
} | ||
@catch (NSException *exception) { | ||
if (error) { | ||
*error = [[NSError alloc] initWithDomain:ARTAblyErrorDomain code:ARTClientCodeErrorInvalidType userInfo:@{NSLocalizedDescriptionKey: exception.reason}]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mattheworiordan I decided to not use the isValidJSONObject
method because it doesn't tell us why it isn't valid. On the other hand, catching the exception gives us more details about the failure.
Source/ARTChannel.m
Outdated
[self.logger error:@"ARTChannel: error encoding data: %@", error]; | ||
[NSException raise:NSInvalidArgumentException format:@"ARTChannel: error encoding data: %@", error]; | ||
message = [message encodeWithEncoder:self.dataEncoder error:error]; | ||
if (error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
error && *error
; error
alone will be true just by passing a non-null NSError **
.
In fact, so that we always log this, and not only when error
is passed, we should do something like:
NSError *e = nil;
message = [message encodeWithEncoder:self.dataEncoder error:&e];
if (e) {
[self.logger error:@"ARTChannel: error encoding data: %@", e];
}
if (error) {
*error = e;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done f4619aa
Source/ARTEncoder.h
Outdated
@@ -43,8 +43,8 @@ ART_ASSUME_NONNULL_BEGIN | |||
- (art_nullable NSData *)encodePresenceMessage:(ARTPresenceMessage *)message; | |||
- (art_nullable NSData *)encodePresenceMessages:(NSArray *)messages; | |||
|
|||
- (art_nullable NSData *)encodeProtocolMessage:(ARTProtocolMessage *)message; | |||
- (art_nullable ARTProtocolMessage *)decodeProtocolMessage:(NSData *)data; | |||
- (art_nullable NSData *)encodeProtocolMessage:(ARTProtocolMessage *)message error:(NSError * __autoreleasing *)error; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure __autoreleasing
is necessary, but I think __Nullable
is: NSError *_Nullable *_Nullable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did that because I took a look at the NSJSONSerialization
header file that returns errors as well 😅 [NSJSONSerialization JSONObjectWithData:<#(nonnull NSData *)#> options:<#(NSJSONReadingOptions)#> error:<#(NSError * _Nullable __autoreleasing * _Nullable)#>]
Source/ARTRealtime.m
Outdated
@@ -810,12 +811,28 @@ - (BOOL)isActive { | |||
- (void)sendImpl:(ARTProtocolMessage *)msg callback:(void (^)(ARTStatus *))cb { | |||
if (msg.ackRequired) { | |||
msg.msgSerial = [NSNumber numberWithLongLong:self.msgSerial++]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be moved below the error handling, so that errors don't increase msgSerial.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tcard Ah you're right. So I need to encode it twice?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about decrementing the msgSerial if the encode fails?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah right, I didn't notice we need the updated value. I think msg.msgSerial = [NSNumber numberWithLongLong:self.msgSerial + 1]
here and then below just self.msgSerial++;
would be the simplest.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done f4619aa. Thanks
Spec/Utilities.swift
Outdated
done() | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing a test for incoming malformed JSON.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Also for malformed MsgPack, BTW.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done: c4de4b9
Ok, so we would like to extend these tests so that they additionally cover incoming invalid/non-encodeable payloads for both binary (msgpack) and text (JSON) transports i.e. if the client library receives a payload that causes a native encoding fault / exception, then the library must handle that in a way that does not cause it to crash. We need to test that both for REST and Realtime. |
3f74c2e
to
7288dce
Compare
05c17c1
to
7073b04
Compare
7073b04
to
05cc875
Compare
* Test: JSON encoder using invalid types * Test: should handle and emit the invalid data error * Fix: handle and emit the invalid data encoder error * Update existing tests * Test: should decode data with malformed JSON * fixup! Fix: handle and emit the invalid data encoder error * Test: should decode data with malformed MsgPack * Test: incoming invalid/non-encodeable payloads and messages * Add error argument on every encode/decode method * Update tests * fixup! Add error argument on every encode/decode method * TestProxyTransport: sendWithData needs to capture protocol messages * Add missing authDetailsFromDictionary * fixup! Add error argument on every encode/decode method * Fix: invalid type cast * Fix: bad access crash * Fix test * fixup! Fix: bad access crash * Fix: missing encoder fields * If message error is empty then use the reason prop * Keep the original error domain to give more context * Transport: use only one way to send data
#591