Skip to content

Commit 97667c0

Browse files
authored
Merge pull request #2972 from spevans/pr_sr_13979_54
[5.4] SR-13979: Calendar.nextDate() segmentation fault
2 parents 25fb4c9 + aabe9f9 commit 97667c0

File tree

5 files changed

+28
-3
lines changed

5 files changed

+28
-3
lines changed

CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ CF_PRIVATE Boolean __CFAllocatorRespectsHintZeroWhenAllocating(CFAllocatorRef _N
9393
static CFOptionFlags _CFAllocatorHintZeroWhenAllocating = 1;
9494

9595
CF_CROSS_PLATFORM_EXPORT Boolean _CFCalendarGetNextWeekend(CFCalendarRef calendar, _CFCalendarWeekendRange *range);
96-
CF_CROSS_PLATFORM_EXPORT void _CFCalendarEnumerateDates(CFCalendarRef calendar, CFDateRef start, CFDateComponentsRef matchingComponents, CFOptionFlags opts, void (^block)(CFDateRef, Boolean, Boolean*));
96+
CF_CROSS_PLATFORM_EXPORT void _CFCalendarEnumerateDates(CFCalendarRef calendar, CFDateRef start, CFDateComponentsRef matchingComponents, CFOptionFlags opts, void (^block)(CFDateRef _Nullable, Boolean, Boolean*));
9797
CF_EXPORT void CFCalendarSetGregorianStartDate(CFCalendarRef calendar, CFDateRef _Nullable date);
9898
CF_EXPORT _Nullable CFDateRef CFCalendarCopyGregorianStartDate(CFCalendarRef calendar);
9999

CoreFoundation/Locale.subproj/CFCalendar_Enumerate.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2123,7 +2123,7 @@ static CFDateRef _Nullable _CFCalendarCreateAdjustedDateForMismatches(CFCalendar
21232123
#pragma mark -
21242124
#pragma mark Enumerate Entry Point
21252125

2126-
CF_CROSS_PLATFORM_EXPORT void _CFCalendarEnumerateDates(CFCalendarRef calendar, CFDateRef start, CFDateComponentsRef matchingComponents, CFOptionFlags opts, void (^block)(CFDateRef, Boolean, Boolean*)) {
2126+
CF_CROSS_PLATFORM_EXPORT void _CFCalendarEnumerateDates(CFCalendarRef calendar, CFDateRef start, CFDateComponentsRef matchingComponents, CFOptionFlags opts, void (^block)(CFDateRef _Nullable, Boolean, Boolean*)) {
21272127
if (!start || !_CFCalendarVerifyCalendarOptions(opts) || !_CFCalendarVerifyCFDateComponentsValues(calendar, matchingComponents)) {
21282128
return;
21292129
}

CoreFoundation/Locale.subproj/CFCalendar_Internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ CF_PRIVATE _Nullable CFDateRef _CFCalendarCreateStartDateForTimeRangeOfUnitForDa
108108
CF_PRIVATE _Nullable CFDateIntervalRef _CFCalendarCreateDateInterval(CFAllocatorRef allocator, CFCalendarRef calendar, CFCalendarUnit unit, CFDateRef date);
109109
CF_PRIVATE _Nullable CFDateRef _CFCalendarCreateDateByAddingValueOfUnitToDate(CFCalendarRef calendar, CFIndex val, CFCalendarUnit unit, CFDateRef date);
110110

111-
CF_CROSS_PLATFORM_EXPORT void _CFCalendarEnumerateDates(CFCalendarRef calendar, CFDateRef start, CFDateComponentsRef matchingComponents, CFOptionFlags opts, void (^block)(CFDateRef, Boolean, Boolean*));
111+
CF_CROSS_PLATFORM_EXPORT void _CFCalendarEnumerateDates(CFCalendarRef calendar, CFDateRef start, CFDateComponentsRef matchingComponents, CFOptionFlags opts, void (^block)(CFDateRef _Nullable, Boolean, Boolean*));
112112

113113
CF_EXPORT void CFCalendarSetGregorianStartDate(CFCalendarRef calendar, CFDateRef _Nullable date);
114114
CF_EXPORT _Nullable CFDateRef CFCalendarCopyGregorianStartDate(CFCalendarRef calendar);

Sources/Foundation/NSCalendar.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1050,6 +1050,10 @@ open class NSCalendar : NSObject, NSCopying, NSSecureCoding {
10501050

10511051
withoutActuallyEscaping(block) { (nonescapingBlock) in
10521052
_CFCalendarEnumerateDates(_cfObject, start._cfObject, comps._createCFDateComponents(), CFOptionFlags(opts.rawValue)) { (cfDate, exact, stop) in
1053+
guard let cfDate = cfDate else {
1054+
stop.pointee = true
1055+
return
1056+
}
10531057
var ourStop: ObjCBool = false
10541058
nonescapingBlock(cfDate._swiftObject, exact, &ourStop)
10551059
if ourStop.boolValue {

Tests/Foundation/Tests/TestCalendar.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,26 @@ class TestCalendar: XCTestCase {
268268
XCTAssertGreaterThan(cal.eraSymbols.count, 0)
269269
}
270270

271+
func test_nextDate() throws {
272+
var calendar = Calendar.current
273+
calendar.timeZone = try XCTUnwrap(TimeZone(identifier: "US/Pacific"))
274+
let date_20200101 = try XCTUnwrap(calendar.date(from: DateComponents(year: 2020, month: 01, day: 1)))
275+
276+
do {
277+
let expected = try XCTUnwrap(calendar.date(from: DateComponents(year: 2020, month: 01, day: 2, hour: 0)))
278+
let components = DateComponents(year: 2020, month: 1, day: 2, hour: 0, minute: 0, second: 0)
279+
let next = calendar.nextDate(after: date_20200101, matching: components, matchingPolicy: .nextTimePreservingSmallerComponents, direction: .forward)
280+
XCTAssertEqual(next, expected)
281+
}
282+
283+
do {
284+
// SR-13979 - Check nil result when no valid nextDate
285+
let components = DateComponents(year: 2019, month: 2, day: 1, hour: 0, minute: 0, second: 0)
286+
let next = calendar.nextDate(after: date_20200101, matching: components, matchingPolicy: .nextTimePreservingSmallerComponents, direction: .forward)
287+
XCTAssertNil(next)
288+
}
289+
}
290+
271291
static var allTests: [(String, (TestCalendar) -> () throws -> Void)] {
272292
return [
273293
("test_allCalendars", test_allCalendars),
@@ -287,6 +307,7 @@ class TestCalendar: XCTestCase {
287307
("test_hashing", test_hashing),
288308
("test_dateFromDoesntMutate", test_dateFromDoesntMutate),
289309
("test_sr10638", test_sr10638),
310+
("test_nextDate", test_nextDate),
290311
]
291312
}
292313
}

0 commit comments

Comments
 (0)