2017-06-01 1 views
0

De http://www.openradar.me/20404230:débordement de pile dans le - [NSString (NSURLUtilities) stringByAddingPercentEncodingWithAllowedCharacters:]

Méthode - [NSString (NSURLUtilities) stringByAddingPercentEncodingWithAllowedCharacters:] a un problème de débordement de la pile, qui peut être reproduit avec des chaînes contenant Hiéroglyphes. Dans ce cas, __stack_chk_fail annulera l'application lors de la construction de l'architecture arm64, et la pile sera corrompue lors de la construction de armv7.

Exemple de https://github.com/PavelTretyakov/nsstring-crash se bloque sur iOS 8.2:

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

Exemple de https://gist.github.com/clowwindy/0d800f07a5e95e5c4dd0 se bloque sur 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]]; 

Exemple de https://github.com/Alamofire/Alamofire/issues/206 se bloque sur iOS 7 à iOS 8.2:

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

Répondre

0

L'identification d'une solution de contournement pour le problème de mémoire a été fournie par PrideChung dans https://github.com/Alamofire/Alamofire/issues/206. La description suivante a ensuite été donnée par cnoon:

Après le débogage beaucoup, j'ai pu suivre cette question jusqu'à ne se produisant dans Alamofire sur iOS 8.1 et 8.2 en utilisant l'iPhone 4S et iPhone 5 simulateurs. Il est reproductible à 100%, mais s'écrase de différentes manières en fonction de la taille de la chaîne chinoise transmise. C'est toujours une forme d'erreur malloc.

[...]

Batching est nécessaire pour échapper en raison d'un bug interne dans iOS 8.1 et 8.2. L'encodage de plus de quelques centaines de caractères chinois provoque plusieurs erreurs d'erreur malloc. Pour éviter ce problème, le traitement par lots DOIT être utilisé pour l'encodage.

Et ma solution réelle, inspirée par AlamoFire, est:

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 
     } 
    } 
}