2017-06-01 22 views
0

http://www.openradar.me/20404230堆栈溢出 - [的NSString(NSURLUtilities)stringByAddingPercentEncodingWithAllowedCharacters:]

的方法 - [的NSString(NSURLUtilities)stringByAddingPercentEncodingWithAllowedCharacters:]具有堆栈溢出的问题,这可以用含有象形文字某些字符串被再现。在这些情况下,__stack_chk_fail将在构建arm64体系结构时中止应用程序,并且在构建armv7时堆栈将会损坏。从https://github.com/PavelTretyakov/nsstring-crash

实施例将崩溃在iOS 8.2:

NSString *str = @"/Users/zaryanov/Movies/rootfolder/시티 오브 히어로 (City of Heroes)/로니 리 가드너 (1961년부터 2010년까지)는 1985 년에 살인죄로 사형을받은 유타 주에서 총살형 된 미국의 악당이었다. 1984 년에 그는 솔트 레이크 시티에서 강도 동안 바텐더를 살해.m4v"; 
str = [str stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPathAllowedCharacterSet]]; 

https://gist.github.com/clowwindy/0d800f07a5e95e5c4dd0实施例将崩溃在iOS 8.1:

NSString *base64String = @"5a+55LqOTGF1bmNoZXLov5nnsbvkuqflk4HmnaXor7TvvIzlroPlvojlrrnmmJPorqnkurrku6zpmbflhaXov5nmmK/lt6Xlhbfov5jmmK/lubPlj7DnmoTkuonmiafkuK3jgILkuI3ov4flnKjmnY7mtpvnnIvmnaXvvIzov5nnp43kuonmiaflrozlhajmmK/kuIDkuKrkvKrlkb3popjvvIzlm6DkuLrkuIDmrL7kuqflk4HnlKjnmoTkurrlpJrkuoblroPoh6rnhLblsLHmmK/lubPlj7DvvIznlKjnmoTkurrlsJHkuoblroPku4DkuYjpg73kuI3mmK/jgILln7rkuo7mraTvvIzmnY7mtpvlhbblrp7lubbmsqHmnInov4flpJrnmoTljrvogIPomZFBUFVTIExhdW5jaGVy6KaB5YGa5bmz5Y+w6L+Y5piv5bel5YW377yM5LuW5oOz55qE5pu05aSa55qE5piv5aaC5L2V6Kej5Yaz55So5oi355qE6Zeu6aKY44CC5L2c5Li65LiA5Liq5Y2z55SoaU9T5Y+I55SoQW5kcm9pZOeahOeUqOaIt++8jOaIkeacrOS6uueahOS4gOS4quS9k+S8muWwseaYr2lQaG9uZeS8mue7meS6uuS4gOenjeS9oOi2iueUqOi2iuinieW+l+Wug+WlveeUqOeahOaEn+inie+8jOS9hkFuZHJvaWTlsLHkuI3kvJrjgILmiYDku6VBUFVTIExhdW5jaGVy546w5Zyo5bCx6KaB6Kej5Yaz6L+Z5Liq6Zq+6aKY77yM6K6pQW5kcm9pZOWPmOW+l+WlveeUqOOAgui/meS5n+aYr+S4uuS9leadjua2m+S8muivtOiHquW3seWBmueahOS4jeaYr+S4gOS4qkxhdW5jaGVy6ICM5piv5LiA5aWX4oCc55So5oi357O757uf4oCd44CC"; 
NSData *decodedData = [[NSData alloc] initWithBase64EncodedString:base64String options:0]; 
NSString *str = [[NSString alloc] initWithData:decodedData encoding:NSUTF8StringEncoding]; 
str = [str stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]]; 

https://github.com/Alamofire/Alamofire/issues/206实施例将在iOS 7崩溃到iOS 8.2:

let str = String(repeating: "一二三四五六七八九十", count: 2_000) 
var allowedCharacterSet = CharacterSet.urlQueryAllowed 
allowedCharacterSet.remove(charactersIn: ":#[]@!$&'()*+,;=") 
_ = str.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) 

回答

0

PrideChung在https://github.com/Alamofire/Alamofire/issues/206中提供了有关内存问题的解决方法。下面的描述随后由cnoon提供:

经过很多调试之后,我能够使用iPhone 4S和iPhone 5模拟器在iOS 8.1和8.2的Alamofire中发现这一问题。它是100%可重复的,但是根据传入的中文字符串的大小以不同的方式崩溃。它总是某种形式的malloc错误。

[...]

配料需要在IOS 8.1和8.2,由于逸出到一个内部错误。编码超过几百个中文字符会导致各种malloc错误崩溃。为了避免这个问题,批处理必须用于编码。

而我实际的解决办法,按AlamoFire的启发,就是:

extension String { 
    // Due to an internal bug in iOS 7.x, 8.1 and 8.2, encoding more 
    // than a few hundred Unicode characters causes various malloc error crashes. 
    // To avoid this issue, batching MUST be used for encoding. 
    //  - https://github.com/Alamofire/Alamofire/issues/206 
    //  - https://stackoverflow.com/a/44309416/1033581 
    func safeAddingPercentEncoding(withAllowedCharacters allowedCharacters: CharacterSet) -> String? { 
     if #available(iOS 8.3, *) { 
      return addingPercentEncoding(withAllowedCharacters: allowedCharacters) 
     } else { 
      let batchSize = 50 
      var batchPosition = startIndex 
      var escaped = "" 
      while batchPosition != endIndex { 
       let range = batchPosition ..< (index(batchPosition, offsetBy: batchSize, limitedBy: endIndex) ?? endIndex) 
       guard let percentEncodedSubstring = substring(with: range).addingPercentEncoding(withAllowedCharacters: allowedCharacters) else { 
        return nil 
       } 
       escaped.append(percentEncodedSubstring) 
       batchPosition = range.upperBound 
      } 
      return escaped 
     } 
    } 
}