Skip to content

iOS15.4 in_app_purchase got crash because of Unsupported value for standard codec #100458

@sy5075391

Description

@sy5075391

the crash occur on iOS15.4, when cancelling the sign

I think the reason is that the err data of in-app purchases cannot be parsed by flutter on iOS15.4

crash:
Unsupported value for standard codec

0 CoreFoundation
___exceptionPreprocess + 220
2 Foundation
__userInfoForFileAndLine
3 Flutter
-[FlutterStandardWriter writeValue:] (FlutterStandardCodec.mm:327)
4 Flutter
-[FlutterStandardWriter writeValue:] (FlutterStandardCodec.mm:335)
5 Flutter
-[FlutterStandardWriter writeValue:] (FlutterStandardCodec.mm:335)
6 Flutter
-[FlutterStandardWriter writeValue:] (FlutterStandardCodec.mm:335)
7 Flutter
-[FlutterStandardWriter writeValue:] (FlutterStandardCodec.mm:335)
8 Flutter
-[FlutterStandardWriter writeValue:] (FlutterStandardCodec.mm:335)
9 Flutter
-[FlutterStandardWriter writeValue:] (FlutterStandardCodec.mm:335)
10 Flutter
-[FlutterStandardWriter writeValue:] (FlutterStandardCodec.mm:335)
11 Flutter
-[FlutterStandardWriter writeValue:] (FlutterStandardCodec.mm:327)
12 Flutter
-[FlutterStandardMethodCodec encodeMethodCall:] (FlutterStandardCodec.mm:95)
13 Flutter
-[FlutterMethodChannel invokeMethod:arguments:] (FlutterChannels.mm:219)
14 in_app_purchase
-[InAppPurchasePlugin handleTransactionsUpdated:] (InAppPurchasePlugin.m:306)
15 in_app_purchase
__41-[InAppPurchasePlugin initWithRegistrar:]_block_invoke (InAppPurchasePlugin.m:0)

I'm guessing there is a problem here: FIAObjectTranslator.m (in_app_ purchase )

+ (NSDictionary *)getMapFromNSError:(NSError *)error {
  if (!error) {
    return nil;
  }
  NSMutableDictionary *userInfo = [NSMutableDictionary new];
  for (NSErrorUserInfoKey key in error.userInfo) {
    id value = error.userInfo[key];
    if ([value isKindOfClass:[NSError class]]) {
      userInfo[key] = [FIAObjectTranslator getMapFromNSError:value];
    } else if ([value isKindOfClass:[NSURL class]]) {
      userInfo[key] = [value absoluteString];
    } else {
      userInfo[key] = value;   ///   -->  There may be other types that cannot be resolved by flutter  on iOS15.4 <--
    }
  }
  return @{@"code" : @(error.code), @"domain" : error.domain ?: @"", @"userInfo" : userInfo};
}

FlutterStandardCodec.mm.

- (void)writeValue:(id)value {
   if (value == nil || value == [NSNull null]) {
     [self writeByte:FlutterStandardFieldNil];
   } else if ([value isKindOfClass:[NSNumber class]]) {
     CFNumberRef number = (CFNumberRef)value;
     BOOL success = NO;
     if (CFGetTypeID(number) == CFBooleanGetTypeID()) {
       BOOL b = CFBooleanGetValue((CFBooleanRef)number);
       [self writeByte:(b ? FlutterStandardFieldTrue : FlutterStandardFieldFalse)];
       success = YES;
     } else if (CFNumberIsFloatType(number)) {
       Float64 f;
       success = CFNumberGetValue(number, kCFNumberFloat64Type, &f);
       if (success) {
         [self writeByte:FlutterStandardFieldFloat64];
         [self writeAlignment:8];
         [self writeBytes:(UInt8*)&f length:8];
       }
     } else if (CFNumberGetByteSize(number) <= 4) {
       SInt32 n;
       success = CFNumberGetValue(number, kCFNumberSInt32Type, &n);
       if (success) {
         [self writeByte:FlutterStandardFieldInt32];
         [self writeBytes:(UInt8*)&n length:4];
       }
     } else if (CFNumberGetByteSize(number) <= 8) {
       SInt64 n;
       success = CFNumberGetValue(number, kCFNumberSInt64Type, &n);
       if (success) {
         [self writeByte:FlutterStandardFieldInt64];
         [self writeBytes:(UInt8*)&n length:8];
       }
     }
     if (!success) {
       NSLog(@"Unsupported value: %@ of number type %ld", value, CFNumberGetType(number));
       NSAssert(NO, @"Unsupported value for standard codec");
     }
   } else if ([value isKindOfClass:[NSString class]]) {
     NSString* string = value;
     [self writeByte:FlutterStandardFieldString];
     [self writeUTF8:string];
   } else if ([value isKindOfClass:[FlutterStandardTypedData class]]) {
     FlutterStandardTypedData* typedData = value;
     [self writeByte:FlutterStandardFieldForDataType(typedData.type)];
     [self writeSize:typedData.elementCount];
     [self writeAlignment:typedData.elementSize];
     [self writeData:typedData.data];
   } else if ([value isKindOfClass:[NSData class]]) {
     [self writeValue:[FlutterStandardTypedData typedDataWithBytes:value]];
   } else if ([value isKindOfClass:[NSArray class]]) {
     NSArray* array = value;
     [self writeByte:FlutterStandardFieldList];
     [self writeSize:array.count];
     for (id object in array) {
       [self writeValue:object];
     }
   } else if ([value isKindOfClass:[NSDictionary class]]) {
     NSDictionary* dict = value;
     [self writeByte:FlutterStandardFieldMap];
     [self writeSize:dict.count];
     for (id key in dict) {
       [self writeValue:key];
       [self writeValue:[dict objectForKey:key]];
     }
   } else {
     NSLog(@"Unsupported value: %@ of type %@", value, [value class]);
     NSAssert(NO, @"Unsupported value for standard codec");
   }
 }

Metadata

Metadata

Assignees

Labels

P1High-priority issues at the top of the work lista: productionIssues experienced in live production appsc: crashStack traces logged to the consolec: fatal crashCrashes that terminate the processp: in_app_purchasePlugin for in-app purchasepackageflutter/packages repository. See also p: labels.platform-iosiOS applications specificallyr: fixedIssue is closed as already fixed in a newer version

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions