Skip to content

Commit 3e00d00

Browse files
authored
Merge pull request #6398 from phausler/data_over_free_fix
[Foundation] Correct case of over-released data contents when specifying .none as a deallocator
2 parents 744e4a6 + b57752a commit 3e00d00

File tree

2 files changed

+23
-7
lines changed

2 files changed

+23
-7
lines changed

stdlib/public/SDK/Foundation/Data.swift

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ public final class _DataStorage {
9191
num -= pages
9292
}
9393
if num > 0 {
94-
memmove(dest, source, num)
94+
memmove(dest, source!, num)
9595
}
9696
}
9797

@@ -500,7 +500,7 @@ public final class _DataStorage {
500500
}
501501
if replacementLength != 0 {
502502
if replacementBytes != nil {
503-
memmove(mutableBytes! + start, replacementBytes, replacementLength)
503+
memmove(mutableBytes! + start, replacementBytes!, replacementLength)
504504
} else {
505505
memset(mutableBytes! + start, 0, replacementLength)
506506
}
@@ -822,7 +822,10 @@ public final class _DataStorage {
822822
if lhs.bytes == rhs.bytes {
823823
return true
824824
}
825-
return memcmp(lhs._bytes, rhs._bytes, length1) == 0
825+
if length1 > 0 {
826+
return memcmp(lhs._bytes!, rhs._bytes!, length1) == 0
827+
}
828+
return true
826829
}
827830
}
828831

@@ -932,15 +935,15 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
932935
/// A custom deallocator.
933936
case custom((UnsafeMutableRawPointer, Int) -> Void)
934937

935-
fileprivate var _deallocator : ((UnsafeMutableRawPointer, Int) -> Void)? {
938+
fileprivate var _deallocator : ((UnsafeMutableRawPointer, Int) -> Void) {
936939
#if DEPLOYMENT_RUNTIME_SWIFT
937940
switch self {
938941
case .unmap:
939942
return { __NSDataInvokeDeallocatorUnmap($0, $1) }
940943
case .free:
941944
return { __NSDataInvokeDeallocatorFree($0, $1) }
942945
case .none:
943-
return nil
946+
return { _, _ in }
944947
case .custom(let b):
945948
return { (ptr, len) in
946949
b(ptr, len)
@@ -955,7 +958,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
955958
case .free:
956959
return { __NSDataInvokeDeallocatorFree($0, $1) }
957960
case .none:
958-
return nil
961+
return { _, _ in }
959962
case .custom(let b):
960963
return { (ptr, len) in
961964
b(ptr, len)
@@ -1639,7 +1642,10 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
16391642
if backing1.bytes == backing2.bytes {
16401643
return true
16411644
}
1642-
return memcmp(backing1.bytes, backing2.bytes, length1) == 0
1645+
if length1 > 0 {
1646+
return memcmp(backing1.bytes!, backing2.bytes!, length1) == 0
1647+
}
1648+
return true
16431649
}
16441650
}
16451651

test/stdlib/TestData.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,15 @@ class TestData : TestDataSuper {
898898

899899
expectTrue(deallocated)
900900
}
901+
902+
func test_doubleDeallocation() {
903+
let data = "12345679".data(using: .utf8)!
904+
let len = data.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) -> Int in
905+
let slice = Data(bytesNoCopy: UnsafeMutablePointer(mutating: bytes), count: 1, deallocator: .none)
906+
return slice.count
907+
}
908+
expectEqual(len, 1)
909+
}
901910
}
902911

903912
#if !FOUNDATION_XCTEST
@@ -941,6 +950,7 @@ DataTests.test("test_classForCoder") { TestData().test_classForCoder() }
941950
DataTests.test("test_AnyHashableContainingData") { TestData().test_AnyHashableContainingData() }
942951
DataTests.test("test_AnyHashableCreatedFromNSData") { TestData().test_AnyHashableCreatedFromNSData() }
943952
DataTests.test("test_noCopyBehavior") { TestData().test_noCopyBehavior() }
953+
DataTests.test("test_doubleDeallocation") { TestData().test_doubleDeallocation() }
944954

945955
// XCTest does not have a crash detection, whereas lit does
946956
DataTests.test("bounding failure subdata") {

0 commit comments

Comments
 (0)