Files
flipper/iOS/Plugins/FlipperKitNetworkPlugin/FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.mm
Mark Tolmacs e44c7f4062 Fix IOS crash in Network Plugin due to incorrect processing of data U… (#978)
Summary:
Fix IOS crash in Network Plugin due to incorrect processing of data URLs (https://github.com/facebook/flipper/issues/974)

Fix https://github.com/facebook/flipper/issues/974 by skipping response processing in FlipperKitNetworkPlugin.mm if the response is not an instance of NSHTTPURLResponse, which data URLs are not. My assumption is that data URLs are not the ones Flipper Network Plugin users are interested in, given the type of information being extracted in the didObserveResponse method which are only present in NSHTTPURLReponse types.

## Changelog
Fix IOS crash in Network Plugin due to unchecked casting of data URLs
Pull Request resolved: https://github.com/facebook/flipper/pull/978

Test Plan:
1. `npx react-native init issue974 --version react-native@0.62.1`
2. `cd issue974/ios/Pods/FlipperKit/iOS/Plugins/`
3. `curl -L https://patch-diff.githubusercontent.com/raw/facebook/flipper/pull/978.patch | git apply -v -p3`
4.  `cd ../../../../../`
5. `curl -L https://github.com/facebook/flipper/files/4434063/rn-data-uri-test.patch.txt | git apply -v
react-native run-ios`
6. Verify that the app does not crash the IOS app with
```
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason:
'-[NSURLResponse allHeaderFields]: unrecognized selector sent to instance <memaddr>'
```

#### The React Native app patch used to verify the PR working and resolving the issue https://github.com/facebook/flipper/issues/974
[rn-data-uri-test.patch.txt](https://github.com/facebook/flipper/files/4434063/rn-data-uri-test.patch.txt)

Reviewed By: mweststrate

Differential Revision: D20861168

Pulled By: cekkaewnumchai

fbshipit-source-id: bae960650ecc0efbb8ae4641aba4c62c74f06bf0
2020-04-08 03:08:58 -07:00

128 lines
3.7 KiB
Plaintext

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#if FB_SONARKIT_ENABLED
#import "FlipperKitNetworkPlugin.h"
#import <iostream>
#import <memory>
#import <vector>
#import "SKBufferingPlugin+CPPInitialization.h"
#import "SKDispatchQueue.h"
#import "SKNetworkReporter.h"
#import "SonarKitNetworkPlugin+CPPInitialization.h"
@interface FlipperKitNetworkPlugin ()
@end
@implementation FlipperKitNetworkPlugin
- (void)setAdapter:(id<SKNetworkAdapterDelegate>)adapter {
_adapter = adapter;
_adapter.delegate = self;
}
- (instancetype)init {
if (self = [super initWithQueue:dispatch_queue_create(
"com.sonarkit.network.buffer",
DISPATCH_QUEUE_SERIAL)]) {
}
return self;
}
- (instancetype)initWithNetworkAdapter:(id<SKNetworkAdapterDelegate>)adapter {
if (self = [super initWithQueue:dispatch_queue_create(
"com.sonarkit.network.buffer",
DISPATCH_QUEUE_SERIAL)]) {
adapter.delegate = self;
_adapter = adapter;
}
return self;
}
- (instancetype)initWithNetworkAdapter:(id<SKNetworkAdapterDelegate>)adapter
queue:(dispatch_queue_t)queue;
{
if (self = [super initWithQueue:queue]) {
adapter.delegate = self;
_adapter = adapter;
}
return self;
}
#pragma mark - SKNetworkReporterDelegate
- (void)didObserveRequest:(SKRequestInfo*)request {
NSMutableArray<NSDictionary<NSString*, id>*>* headers = [NSMutableArray new];
for (NSString* key in [request.request.allHTTPHeaderFields allKeys]) {
NSDictionary<NSString*, id>* header =
@{@"key" : key, @"value" : request.request.allHTTPHeaderFields[key]};
[headers addObject:header];
}
NSString* body = request.body;
[self send:@"newRequest"
sonarObject:@{
@"id" : @(request.identifier),
@"timestamp" : @(request.timestamp),
@"method" : request.request.HTTPMethod ?: [NSNull null],
@"url" : [request.request.URL absoluteString] ?: [NSNull null],
@"headers" : headers,
@"data" : body ? body : [NSNull null]
}];
}
- (void)didObserveResponse:(SKResponseInfo*)response {
// Only track HTTP(S) calls, data URLs cannot be casted to NSHTTPURLResponse
if (![response.response isKindOfClass:[NSHTTPURLResponse class]]) {
return;
}
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response.response;
NSMutableArray<NSDictionary<NSString*, id>*>* headers = [NSMutableArray new];
for (NSString* key in [httpResponse.allHeaderFields allKeys]) {
NSDictionary<NSString*, id>* header =
@{@"key" : key, @"value" : httpResponse.allHeaderFields[key]};
[headers addObject:header];
}
NSString* body = response.body;
[self send:@"newResponse"
sonarObject:@{
@"id" : @(response.identifier),
@"timestamp" : @(response.timestamp),
@"status" : @(httpResponse.statusCode),
@"reason" : [NSHTTPURLResponse
localizedStringForStatusCode:httpResponse.statusCode]
?: [NSNull null],
@"headers" : headers,
@"data" : body ? body : [NSNull null]
}];
}
@end
@implementation FlipperKitNetworkPlugin (CPPInitialization)
- (instancetype)initWithNetworkAdapter:(id<SKNetworkAdapterDelegate>)adapter
dispatchQueue:
(std::shared_ptr<facebook::flipper::DispatchQueue>)
queue {
if (self = [super initWithDispatchQueue:queue]) {
adapter.delegate = self;
_adapter = adapter;
}
return self;
}
@end
#endif