You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@weex.apache.org by mo...@apache.org on 2019/09/23 13:27:13 UTC

[incubator-weex] branch master updated: [iOS] Protect for invalid JSON object on iOS13 which will crash.

This is an automated email from the ASF dual-hosted git repository.

moshen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-weex.git


The following commit(s) were added to refs/heads/master by this push:
     new 1461699  [iOS] Protect for invalid JSON object on iOS13 which will crash.
     new 315f88f  Merge pull request #2931 from wqyfavor/fix_json_crash_ios13
1461699 is described below

commit 146169900bdc8093cec47817d3dccfc9d763be23
Author: qianyuan.wqy <qi...@taobao.com>
AuthorDate: Mon Sep 23 21:08:16 2019 +0800

    [iOS] Protect for invalid JSON object on iOS13 which will crash.
---
 ios/sdk/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 +++
 ios/sdk/WeexSDK/Sources/Utility/WXConvertUtility.h |  8 ++++
 .../WeexSDK/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 e241609..d739d63 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm
@@ -1302,6 +1302,7 @@ break; \
         _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<std::string, std::string> *styles, std::map<std::string, std::string> *attrs, std::set<std::string> *events, int index) {
         if (parentRef.empty()) {
             // is root body
@@ -1343,6 +1344,7 @@ break; \
 {
     RenderPageCustom* page = [self getPage:pageId];
     if (page && page->IsValid()) {
+        SetConvertCurrentPage(pageId);
         page->UpdateAttr([ref UTF8String] ?: "", [WXCustomPageBridge parseMapValuePairs:data]);
     }
 }
@@ -1351,6 +1353,7 @@ break; \
 {
     RenderPageCustom* page = [self getPage:pageId];
     if (page && page->IsValid()) {
+        SetConvertCurrentPage(pageId);
         page->UpdateStyle([ref UTF8String] ?: "", [WXCustomPageBridge parseMapValuePairs:data]);
     }
 }
@@ -1406,6 +1409,7 @@ break; \
         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 @@ break; \
         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 @@ static WeexCore::ScriptBridge* jsBridge = nullptr;
         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 @@ static WeexCore::ScriptBridge* jsBridge = nullptr;
 
 + (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 449ab92..17fa069 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 8d7bc9d..0f06927 100644
--- a/ios/sdk/WeexSDK/Sources/Engine/WXSDKError.m
+++ b/ios/sdk/WeexSDK/Sources/Engine/WXSDKError.m
@@ -105,6 +105,8 @@
                 
                 @(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 1a09028..360ad4f 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 <WeexSDK/WXDataRenderHandler.h>
 
@@ -599,6 +600,11 @@ typedef enum : NSUInteger {
     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 a5e64f5..2cd8f9b 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<std::unordered_map<std::string, std
 
 void ConvertToCString(id _Nonnull obj, void (^ _Nonnull callback)(const char* _Nullable));
 
+extern "C" {
+    void SetConvertCurrentPage(NSString* _Nonnull pageId);
+    void ConvertSwitches(BOOL isIOS13, BOOL invalidJSONObjectUseMRC, BOOL alwaysUseMRC);
+}
+
+#else
+void SetConvertCurrentPage(NSString* _Nonnull pageId);
+void ConvertSwitches(BOOL isIOS13, BOOL invalidJSONObjectUseMRC, BOOL alwaysUseMRC);
 #endif
 
 #endif
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXConvertUtility.mm b/ios/sdk/WeexSDK/Sources/Utility/WXConvertUtility.mm
index bec9105..65d035d 100644
--- a/ios/sdk/WeexSDK/Sources/Utility/WXConvertUtility.mm
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXConvertUtility.mm
@@ -20,10 +20,32 @@
 #import "WXConvertUtility.h"
 #import "WXLog.h"
 #import "WXAssert.h"
+#import "WXExceptionUtils.h"
+#import "WXSDKError.h"
+
 #include <vector>
 #include <string>
 
 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 @@ NSString* TO_JSON(id object)
             _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
 }