Skip to content

Commit 68c0749

Browse files
drodriguezparkera
authored andcommitted
Fix argument order for CFArraySetValueAtIndex. (#1679)
The Swift dispatching of CFArraySetValueAtIndex had the arguments for value and index switched around. If someone creates a Swift NSArray which is eventually bridged to CFArray, and some other piece calls CFArraySetValueAtIndex, CF_SWIFT_FUNCDISPATCHV will delegate to the Swift method, but will send a pointer where CFIndex is expected, and a CFIndex where a pointer is expected, probably causing a segmentation fault. The test tries to simplify the scenario (not easy to create the right conditions) and uses unsafeBitCast (which is the same that happens in the internal _cfObject). The test crashes before the patch is applied.
1 parent a481fd9 commit 68c0749

File tree

2 files changed

+12
-1
lines changed

2 files changed

+12
-1
lines changed

CoreFoundation/Collections.subproj/CFArray.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,7 @@ void CFArrayAppendValue(CFMutableArrayRef array, const void *value) {
628628
}
629629

630630
void CFArraySetValueAtIndex(CFMutableArrayRef array, CFIndex idx, const void *value) {
631-
CF_SWIFT_FUNCDISPATCHV(CFArrayGetTypeID(), void, (CFSwiftRef)array, NSMutableArray.setObject, idx, value);
631+
CF_SWIFT_FUNCDISPATCHV(CFArrayGetTypeID(), void, (CFSwiftRef)array, NSMutableArray.setObject, value, idx);
632632
CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID(), void, (NSMutableArray *)array, setObject:(id)value atIndex:(NSUInteger)idx);
633633
__CFGenericValidateType(array, CFArrayGetTypeID());
634634
CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__);

TestFoundation/TestNSArray.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
88
//
99

10+
import CoreFoundation
11+
1012
class TestNSArray : XCTestCase {
1113

1214
static var allTests: [(String, (TestNSArray) -> () throws -> Void)] {
@@ -42,6 +44,7 @@ class TestNSArray : XCTestCase {
4244
("test_insertObjectsAtIndexes", test_insertObjectsAtIndexes),
4345
("test_replaceObjectsAtIndexesWithObjects", test_replaceObjectsAtIndexesWithObjects),
4446
("test_pathsMatchingExtensions", test_pathsMatchingExtensions),
47+
("test_arrayUsedAsCFArrayInvokesArrayMethods", test_arrayUsedAsCFArrayInvokesArrayMethods),
4548
]
4649
}
4750

@@ -794,6 +797,14 @@ class TestNSArray : XCTestCase {
794797
XCTAssertEqual(match5, [])
795798
}
796799

800+
func test_arrayUsedAsCFArrayInvokesArrayMethods() {
801+
let number = 789 as NSNumber
802+
let array = NSMutableArray(array: [123, 456])
803+
CFArraySetValueAtIndex(unsafeBitCast(array, to: CFMutableArray.self), 1, UnsafeRawPointer(Unmanaged.passUnretained(number).toOpaque()))
804+
XCTAssertEqual(array[0] as! NSNumber, 123 as NSNumber)
805+
XCTAssertEqual(array[1] as! NSNumber, 789 as NSNumber)
806+
}
807+
797808
private func createTestFile(_ path: String, _contents: Data) -> String? {
798809
let tempDir = NSTemporaryDirectory() + "TestFoundation_Playground_" + NSUUID().uuidString + "/"
799810
do {

0 commit comments

Comments
 (0)