【问题标题】:Bug in library causing hundreds of crashes, but I can't pinpoint it. I have the crash data from users, what is causing this crash?库中的错误导致数百次崩溃,但我无法确定它。我有来自用户的崩溃数据,是什么导致了这次崩溃?
【发布时间】:2014-01-24 18:11:05
【问题描述】:

为了对使用 XAuth 的 Instapaper 进行身份验证,我使用 AFXAuthClient,它是 AFNetworking 1.0 的扩展,增加了对身份验证的 XAuth 支持。

对于我 99% 的用户来说,它的效果非常好。但是对于几十个,它导致了大量的崩溃(远远超过我的应用程序中的任何其他崩溃)。我的应用使用 Crashlytics,所以我有每次崩溃的信息,但我不知道如何修复它,甚至不知道如何重新创建它。

信息

Crashlytics 给了我这个错误信息:

致命异常:NSInvalidArgumentException * setObjectForKey: object 不能为 nil (key: oauth_token)

这用于日志:

Thread : Fatal Exception: NSInvalidArgumentException
0  CoreFoundation                 0x2e355f4b __exceptionPreprocess + 130
1  libobjc.A.dylib                0x386e56af objc_exception_throw + 38
2  CoreFoundation                 0x2e291667 -[__NSDictionaryM setObject:forKey:] + 818
3  Syllable                       0x0007511f -[AFXAuthClient authorizationHeaderWithRequest:parameters:] + 224 (AFXAuthClient.m:224)
4  Syllable                       0x000752ad -[AFXAuthClient requestWithMethod:path:parameters:] + 239 (AFXAuthClient.m:239)
5  Syllable                       0x00069377 -[AppDelegate loadInstapaperArticles] + 356 (AppDelegate.m:356)
6  Syllable                       0x000680fb -[AppDelegate application:performFetchWithCompletionHandler:] + 137 (AppDelegate.m:137)
7  UIKit                          0x30d469d1 -[UIApplication _handleOpportunisticFetchWithSequenceNumber:] + 448
8  UIKit                          0x30b38fbb -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 2010
9  UIKit                          0x30b33353 -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 714
10 UIKit                          0x30ace41f -[UIApplication handleEvent:withNewEvent:] + 3130
11 UIKit                          0x30acd721 -[UIApplication sendEvent:] + 72
12 UIKit                          0x30b32b3d _UIApplicationHandleEvent + 664
13 GraphicsServices               0x32f6970d _PurpleEventCallback + 608
14 GraphicsServices               0x32f692f7 PurpleEventCallback + 34
15 CoreFoundation                 0x2e3209df __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 34
16 CoreFoundation                 0x2e32097b __CFRunLoopDoSource1 + 346
17 CoreFoundation                 0x2e31f14f __CFRunLoopRun + 1398
18 CoreFoundation                 0x2e289c27 CFRunLoopRunSpecific + 522
19 CoreFoundation                 0x2e289a0b CFRunLoopRunInMode + 106
20 UIKit                          0x30b31dd9 -[UIApplication _run] + 760
21 UIKit                          0x30b2d049 UIApplicationMain + 1136
22 Syllable                       0x0003817f main + 16 (main.m:16)
23 libdyld.dylib                  0x38bedab7 start + 2

显然应用程序将 nil 传递给 setObjectForKey:。这是它在 AFXAuthClient.m(AFXAuthClient 库的实现文件)中出现的地方(我在行旁放了一个 --> 箭头):

- (NSMutableDictionary *)authorizationHeaderWithRequest:(NSURLRequest *)request parameters:(NSDictionary *)parameters
{
    NSMutableDictionary *authorizationHeader = [[NSMutableDictionary alloc] initWithDictionary:@{@"oauth_nonce": _nonce,
                                                @"oauth_signature_method": @"HMAC-SHA1",
                                                @"oauth_timestamp": _timestamp,
                                                @"oauth_consumer_key": self.consumerKey,
                                                @"oauth_signature": AFHMACSHA1Signature([self baseStringWithRequest:request parameters:parameters], _consumerSecret, _token.secret),
                                                @"oauth_version": @"1.0"}];
    if (self.token)
-->      [authorizationHeader setObject:RFC3986EscapedStringWithEncoding(self.token.key, NSUTF8StringEncoding) forKey:@"oauth_token"];

    return authorizationHeader;
}

在它调用的RFC3986EscapedStringWithEncoding()函数中,开头声明如下:

// Escape per RFC 3986 standards as required by OAuth. Previously, not
// escaping asterisks (*) causes passwords with * to fail in
// Instapaper authentication

我的用户确实在使用 Instapaper 登录,所以这个图书馆过去似乎在使用 Instapaper 时遇到过问题。我不确定在这种情况下是什么原因造成的,甚至不确定如何重现它。

我唯一的理论是 Instapaper 允许您在没有密码的情况下创建帐户,所以当用户在没有密码的情况下登录时,可能会将 nil 传递给setObjectForKey?但是不,我尝试使用无密码帐户,但我的应用根本没有崩溃。

什么可能导致此问题?我将如何解决它?如果我可以从 Crashlytics 提供更多信息,请直接说出来。

【问题讨论】:

  • self.token.keynil(或者当self.tokennil 但你检查了)时,代码会失败。你需要找出在什么条件下是nil。或者至少添加代码来检查是否是 nil 并记录一些调试信息以帮助您追踪它。
  • iOS 中的变量验证有时会变得很棘手。您应该尝试将令牌与您已经使用的nil(id)[NSNull null] 和标准if 进行比较。来自 Web 服务的响应因不同来源而异,但这 3 个“通常”处理大多数验证。

标签: ios objective-c crash afnetworking xauth


【解决方案1】:

首先,确保您使用的是最新版本 - 我看到了 fix from 7 months ago for this issue

其次,如果你是最新的,我会采取这样修改 AFXAuthClient 的方法:

if (self.token) {
    NSString *escapedToken = RFC3986EscapedStringWithEncoding(self.token.key, NSUTF8StringEncoding);
    if (escapedToken) {
        /* guaranteed not to crash here */
        [authorizationHeader setObject:escapedToken forKey:@"oauth_token"];
    } else {
        /* Log self.token you can inspect the types of tokens that are causing
           invalid escapedTokens, perhaps using a service like Flurry. */
    }
}

这将允许您收集导致RFC3986EscapedStringWithEncoding 返回nil 的任何数据。显然,要小心存储/传输这些数据的方式,因为它是用户的身份验证令牌。

另外,它应该将这些崩溃变成失败的身份验证错误,这(可能)更好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多