From 146169900bdc8093cec47817d3dccfc9d763be23 Mon Sep 17 00:00:00 2001 From: "qianyuan.wqy" Date: Mon, 23 Sep 2019 21:08:16 +0800 Subject: [PATCH] [iOS] Protect for invalid JSON object on iOS13 which will crash. --- .../WeexSDK/Sources/Bridge/WXCoreBridge.mm | 8 +++ ios/sdk/WeexSDK/Sources/Engine/WXSDKError.h | 1 + ios/sdk/WeexSDK/Sources/Engine/WXSDKError.m | 2 + ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m | 6 +++ .../Sources/Utility/WXConvertUtility.h | 8 +++ .../Sources/Utility/WXConvertUtility.mm | 53 +++++++++++++++++++ 6 files changed, 78 insertions(+) diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm index e241609235..d739d636ff 100644 --- a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm +++ b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm @@ -1302,6 +1302,7 @@ - (void)callCreateBody:(NSString*)pageId data:(NSDictionary*)data _customPages[sId] = page; } + SetConvertCurrentPage(pageId); [WXCustomPageBridge parseRenderObject:data parentRef:"" index:0 genObject:^(const std::string &ref, const std::string &type, const std::string &parentRef, std::map *styles, std::map *attrs, std::set *events, int index) { if (parentRef.empty()) { // is root body @@ -1343,6 +1344,7 @@ - (void)callUpdateAttrs:(NSString*)pageId ref:(NSString*)ref data:(NSDictionary* { RenderPageCustom* page = [self getPage:pageId]; if (page && page->IsValid()) { + SetConvertCurrentPage(pageId); page->UpdateAttr([ref UTF8String] ?: "", [WXCustomPageBridge parseMapValuePairs:data]); } } @@ -1351,6 +1353,7 @@ - (void)callUpdateStyle:(NSString*)pageId ref:(NSString*)ref data:(NSDictionary* { RenderPageCustom* page = [self getPage:pageId]; if (page && page->IsValid()) { + SetConvertCurrentPage(pageId); page->UpdateStyle([ref UTF8String] ?: "", [WXCustomPageBridge parseMapValuePairs:data]); } } @@ -1406,6 +1409,7 @@ - (BOOL)forwardCallNativeModuleToCustomPage:(NSString*)pageId if (target && target->shouldHandleModuleMethod([moduleName UTF8String] ?: "", [methodName UTF8String] ?: "")) { __block const char* seralizedArguments = nullptr; __block const char* seralizedOptions = nullptr; + SetConvertCurrentPage(pageId); ConvertToCString(arguments, ^(const char * value) { if (value != nullptr) { seralizedArguments = strdup(value); @@ -1495,6 +1499,7 @@ - (void)forwardCallComponentToCustomPage:(NSString*)pageId if (target) { __block const char* seralizedArguments = nullptr; __block const char* seralizedOptions = nullptr; + SetConvertCurrentPage(pageId); ConvertToCString(arguments, ^(const char * value) { if (value != nullptr) { seralizedArguments = strdup(value); @@ -1847,6 +1852,7 @@ + (void)callCreateBody:(NSString*)pageId data:(NSDictionary*)data return; } + SetConvertCurrentPage(pageId); const std::string page([pageId UTF8String] ?: ""); RenderManager::GetInstance()->CreatePage(page, [&] (RenderPage* pageInstance) -> RenderObject* { pageInstance->set_before_layout_needed(false); // we do not need before and after layout @@ -1868,11 +1874,13 @@ + (void)callMoveElement:(NSString*)pageId ref:(NSString*)ref parentRef:(NSString + (void)callUpdateAttrs:(NSString*)pageId ref:(NSString*)ref data:(NSDictionary*)data { + SetConvertCurrentPage(pageId); WeexCore::RenderManager::GetInstance()->UpdateAttr([pageId UTF8String] ?: "", [ref UTF8String] ?: "", [self _parseMapValuePairs:data]); } + (void)callUpdateStyle:(NSString*)pageId ref:(NSString*)ref data:(NSDictionary*)data { + SetConvertCurrentPage(pageId); WeexCore::RenderManager::GetInstance()->UpdateStyle([pageId UTF8String] ?: "", [ref UTF8String] ?: "", [self _parseMapValuePairs:data]); } diff --git a/ios/sdk/WeexSDK/Sources/Engine/WXSDKError.h b/ios/sdk/WeexSDK/Sources/Engine/WXSDKError.h index 449ab92d6e..17fa069270 100644 --- a/ios/sdk/WeexSDK/Sources/Engine/WXSDKError.h +++ b/ios/sdk/WeexSDK/Sources/Engine/WXSDKError.h @@ -107,6 +107,7 @@ typedef NS_ENUM(int, WXSDKErrCode) WX_KEY_EXCEPTION_EMPTY_SCREEN_NATIVE = -9701, WX_KEY_EXCEPTION_NO_BUNDLE_TYPE = -9801, + WX_KEY_EXCEPTION_INVALID_JSON_OBJECT = -9802, WX_KEY_EXCEPTION_HERON_ERROR = -9900, WX_KEY_EXCEPTION_HERON_RENDER_ERROR = -9901, diff --git a/ios/sdk/WeexSDK/Sources/Engine/WXSDKError.m b/ios/sdk/WeexSDK/Sources/Engine/WXSDKError.m index 8d7bc9d9ba..0f06927fe8 100644 --- a/ios/sdk/WeexSDK/Sources/Engine/WXSDKError.m +++ b/ios/sdk/WeexSDK/Sources/Engine/WXSDKError.m @@ -105,6 +105,8 @@ +(NSDictionary *) getMap @(WX_KEY_EXCEPTION_NO_BUNDLE_TYPE):@{ERROR_TYPE:@(WX_JS_ERROR),ERROR_GROUP:@(WX_JS)}, + @(WX_KEY_EXCEPTION_INVALID_JSON_OBJECT):@{ERROR_TYPE:@(WX_JS_ERROR),ERROR_GROUP:@(WX_JS)}, + @(WX_KEY_EXCEPTION_HERON_ERROR):@{ERROR_TYPE:@(WX_NATIVE_ERROR),ERROR_GROUP:@(WX_NATIVE)}, @(WX_KEY_EXCEPTION_HERON_RENDER_ERROR):@{ERROR_TYPE:@(WX_RENDER_ERROR),ERROR_GROUP:@(WX_NATIVE)}, }; diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m index 1a09028f73..360ad4f9bd 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m +++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m @@ -49,6 +49,7 @@ #import "WXJSCoreBridge.h" #import "WXSDKInstance_performance.h" #import "WXPageEventNotifyEvent.h" +#import "WXConvertUtility.h" #import "WXCoreBridge.h" #import @@ -599,6 +600,11 @@ - (BOOL)_handleConfigCenter if ([configCenter respondsToSelector:@selector(configForKey:defaultValue:isDefault:)]) { BOOL enableRTLLayoutDirection = [[configCenter configForKey:@"iOS_weex_ext_config.enableRTLLayoutDirection" defaultValue:@(YES) isDefault:NULL] boolValue]; [WXUtility setEnableRTLLayoutDirection:enableRTLLayoutDirection]; + + BOOL isIOS13 = [[[UIDevice currentDevice] systemVersion] integerValue] == 13; + BOOL useMRCForInvalidJSONObject = [[configCenter configForKey:@"iOS_weex_ext_config.useMRCForInvalidJSONObject" defaultValue:@(YES) isDefault:NULL] boolValue]; + BOOL alwaysUseMRCForObjectToWeexCore = [[configCenter configForKey:@"iOS_weex_ext_config.alwaysUseMRC" defaultValue:@(NO) isDefault:NULL] boolValue]; + ConvertSwitches(isIOS13, useMRCForInvalidJSONObject, alwaysUseMRCForObjectToWeexCore); } return NO; } diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXConvertUtility.h b/ios/sdk/WeexSDK/Sources/Utility/WXConvertUtility.h index a5e64f5da0..2cd8f9bcdf 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXConvertUtility.h +++ b/ios/sdk/WeexSDK/Sources/Utility/WXConvertUtility.h @@ -47,6 +47,14 @@ NSMutableArray* _Nonnull NSARRAY(std::vector #include static NSString* const JSONSTRING_SUFFIX = @"\t\n\t\r"; +static NSString* const OBJC_MRC_SUFFIX = @"\t\t\n\r"; + +static BOOL bIsIOS13 = NO; +static BOOL bUseMRCForInvalidJSONObject = NO; +static BOOL bAlwaysUseMRC = NO; + +static NSString* sCurrentPage = nil; + +void SetConvertCurrentPage(NSString* pageId) +{ + sCurrentPage = pageId; +} + +void ConvertSwitches(BOOL isIOS13, BOOL invalidJSONObjectUseMRC, BOOL alwaysUseMRC) +{ + bIsIOS13 = isIOS13; + bUseMRCForInvalidJSONObject = invalidJSONObjectUseMRC; + bAlwaysUseMRC = alwaysUseMRC; +} #if 0 @@ -78,6 +100,28 @@ void _detectObjectRecursion(id object, NSMutableSet* nodes) _detectObjectRecursion(object, nodes); #endif + if (bAlwaysUseMRC) { + return [NSString stringWithFormat:@"%p%@", (__bridge_retained void*)object, OBJC_MRC_SUFFIX]; + } + + if (bIsIOS13) { + if (![NSJSONSerialization isValidJSONObject:object]) { + [WXExceptionUtils commitCriticalExceptionRT:sCurrentPage + errCode:[NSString stringWithFormat:@"%d", WX_KEY_EXCEPTION_INVALID_JSON_OBJECT] + function:@"" + exception:@"Invalid JSON object." + extParams:nil]; + + // Report for instance. + if (bUseMRCForInvalidJSONObject) { + return [NSString stringWithFormat:@"%p%@", (__bridge_retained void*)object, OBJC_MRC_SUFFIX]; + } + else { + return nil; + } + } + } + NSError *error = nil; NSData *data = [NSJSONSerialization dataWithJSONObject:object options:0 @@ -126,6 +170,15 @@ id TO_OBJECT(NSString* s) WXAssert(NO, @"Fail to convert json to object. %@", exception); } } + else if ([s hasSuffix:OBJC_MRC_SUFFIX]) { + NSScanner* scanner = [NSScanner scannerWithString:s]; + unsigned long long address = 0; + [scanner scanHexLongLong:&address]; + if (address != 0) { + return (__bridge_transfer id)((void*)address); + } + } + return s; // return s instead }