swiftlang / swift-corelibs-foundation

The Foundation Project, providing core utilities, internationalization, and OS independence
swift.org
Apache License 2.0
5.27k stars 1.13k forks source link

[SR-11887] Multibyte characters in NSMutableDictionary keys triggers Address Sanitizer heap-buffer-overflow #3372

Open swift-ci opened 4 years ago

swift-ci commented 4 years ago
Previous ID SR-11887
Radar rdar://FB7476355
Original Reporter mildm8nnered (JIRA User)
Type Bug

Attachment: Download

Environment MacOS 10.14.6 (18G2016) Xcode Version 11.0 (11A420a), Version 11.3 beta (11C24b)
Additional Detail from JIRA | | | |------------------|-----------------| |Votes | 0 | |Component/s | Foundation | |Labels | Bug | |Assignee | None | |Priority | Medium | md5: 5b64ceb18ce7fdc5e87597c679dec9fd

Issue Description:

In the attached project, AsanCrasherTests.testAddLabel will trigger the problem.

In a Swift class with an NSMutableDictionary ivar, adding entries where the key contains a multi-byte character will trigger an Address Sanitizer heap-buffer-overflow warning

It’s quite data-sensitive, but absolutely deterministic - the ASAN is always triggered for the right combination of data, and never triggered otherwise.

The keys for the dictionary entries contain the multi-byte character "▸". If this is changed for, for example, "+", the problem disappears

The equivalent Objective-C code (in AsanCrasherTestsObjC.m in the attached project) does not trigger the problem.

Replacing the NSMutableDictionary with a Swift dictionary also makes the problem go away.

swift-ci commented 4 years ago

Comment by Martin Redington (JIRA)

Here is the offending code

import XCTest

internal class AsanCrasherTests: XCTestCase {

{{ }}

{{ var dictionary: NSMutableDictionary = NSMutableDictionary()}}

{{ }}

{{ internal func addLabel(withKey key: String) {}}

{{ if let instances: NSMutableArray? = dictionary[key] as? NSMutableArray? {}}

{{ if instances != nil {}}

{{ instances?.add(NSObject())}}

{{ } else {}}

{{ dictionary[key] = NSMutableArray(object: NSObject())}}

{{ }}}

{{ }}}

{{ } }}

{{ }}

{{ func testAddLabel() {}}

{{ // Just using string interpolation to make it easier to swap different separators in.}}

{{ // The same thing happens without string iterpolation}}

{{ let separator = "▸"}}

{{ addLabel(withKey: "XY(separator)A")}}

{{ addLabel(withKey: "XXXX ZZZZZZZZ(separator)C DDDDDDDD")}}

{{ addLabel(withKey: "Outcome(separator)E")}}

{{ addLabel(withKey: "FFF FFFF(separator)FFF FFFF")}}

{{ addLabel(withKey: "XY(separator)GGGGG & HHHHH")}}

{{ addLabel(withKey: "XXXX ZZZZZZZZ(separator)JJJ 3")}}

{{ addLabel(withKey: "JJJ 3")}}

{{ addLabel(withKey: "C DDDDDDDD")}}

{{ addLabel(withKey: "XXXX ZZZZZZZZ(separator)K LLLLLL 3")}}

{{ addLabel(withKey: "K LLLLLL 3")}}

{{ addLabel(withKey: "Outcome(separator)+3MN")}}

{{ addLabel(withKey: "+3MN")}}

{{ addLabel(withKey: "XXXX ZZZZZZZZ(separator)O PPPP 3")}}

{{ addLabel(withKey: "O PPPP 3")}}

{{ addLabel(withKey: "GGGGG & HHHHH")}}

{{ addLabel(withKey: "Outcome(separator)-3MN")}}

{{ addLabel(withKey: "-3MN")}}

{{ addLabel(withKey: "XXXX ZZZZZZZZ(separator)Q RRRR 3")}}

{{ addLabel(withKey: "Q RRRR 3")}}

{{ addLabel(withKey: "SSSSSS TTTT(separator)#1 UUUUUUUU")}}

{{ addLabel(withKey: "#1 UUUUUUUU")}}

{{ addLabel(withKey: "XY(separator)VVVVV")}}

{{ addLabel(withKey: "VVVVV")}}

{{ addLabel(withKey: "XXXX ZZZZZZZZ(separator)L WWWWW")}}

{{ addLabel(withKey: "L WWWWW")}}

{{ addLabel(withKey: "SSSSSS TTTT(separator)#4 aaaaaaaaaa")}}

{{ addLabel(withKey: "#4 aaaaaaaaaa")}}

{{ addLabel(withKey: "XY(separator)bbbb bbbb")}}

{{ addLabel(withKey: "bbbb bbbb")}}

{{ addLabel(withKey: "Outcome(separator)-2MN")}}

{{ addLabel(withKey: "XXXX ZZZZZZZZ(separator)c dddddddd")}}

{{ addLabel(withKey: "c dddddddd")}}

{{ addLabel(withKey: "SSSSSS TTTT(separator)#32 eeeeeee")}}

{{ addLabel(withKey: "#32 eeeeeee")}}

{{ addLabel(withKey: "XY(separator)fff gggg")}}

{{ addLabel(withKey: "fff gggg")}}

{{ addLabel(withKey: "FFF FFFF")}}

{{ addLabel(withKey: "E")}}

{{ addLabel(withKey: "XXXX ZZZZZZZZ(separator)h hhhhh")}}

{{ addLabel(withKey: "h hhhhh")}}

{{ addLabel(withKey: "SSSSSS TTTT(separator)#25 iiiii")}}

{{ addLabel(withKey: "#25 iiiii")}}

{{ addLabel(withKey: "A")}}

{{ addLabel(withKey: "-2MN")}}

{{ addLabel(withKey: "XXXX ZZZZZZZZ(separator)k mmmmmmmm")}}

{{ addLabel(withKey: "k mmmmmmmm")}}

{{ addLabel(withKey: "Outcome(separator)DREB")}}

{{ addLabel(withKey: "DREB")}}

{{ addLabel(withKey: "Results(separator)ASSIST")}}

{{ addLabel(withKey: "Outcome(separator)ASSIST #13 nnnnnn")}}

{{ addLabel(withKey: "ASSIST #13 nnnnnn")}}

{{ addLabel(withKey: "ASSIST")}}

{{ addLabel(withKey: "Results(separator)Foul Committed")}}

{{ addLabel(withKey: "Foul Committed")}}

{{ }}}

{{}}}

beccadax commented 4 years ago

@swift-ci create