Skip to content

Commit 00f2869

Browse files
authored
Fix possible crashes caused by incorrect indecies (#4314)
* Fix possible crashes caused by incorrect index with suffix/prefix in arrays
1 parent ca38b1a commit 00f2869

File tree

16 files changed

+426
-168
lines changed

16 files changed

+426
-168
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changes to the Mapbox Navigation SDK for iOS
22

3+
## v2.11.0
4+
5+
### Other changes
6+
7+
* Fixed an issue where an incorrect upcoming intersection index cause a crash. ([#4314](https://github.com/mapbox/mapbox-navigation-ios/pull/4314))
8+
39
## v2.10.0
410

511
### Packaging

MapboxNavigation-SPM.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

MapboxNavigation.xcodeproj/project.pbxproj

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,11 @@
8888
2C193C31290A9BC30050A57F /* PredictiveCacheManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C04E46D290A8CA10067FDCF /* PredictiveCacheManagerTests.swift */; };
8989
2C193C32290A9BC30050A57F /* PredictiveCacheOptionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C04E46C290A8CA10067FDCF /* PredictiveCacheOptionsTests.swift */; };
9090
2C257377292B836B00941307 /* ReentrantImageDownloaderSpy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C257376292B836B00941307 /* ReentrantImageDownloaderSpy.swift */; };
91-
2C257379292B8BEC00941307 /* RouteStepProgressTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C257378292B8BEB00941307 /* RouteStepProgressTests.swift */; };
9291
2C2880A1291A82630063E5B7 /* RerouteControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C2880A0291A82630063E5B7 /* RerouteControllerTests.swift */; };
9392
2C2880A6291AB7A10063E5B7 /* RerouteDetectorSpy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C2880A5291AB7A10063E5B7 /* RerouteDetectorSpy.swift */; };
93+
2C36D9002952256400EE37DF /* RouteLegProgressTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C36D8FD2952256400EE37DF /* RouteLegProgressTests.swift */; };
94+
2C36D9012952256400EE37DF /* RouteStepProgressTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C36D8FE2952256400EE37DF /* RouteStepProgressTests.swift */; };
95+
2C36D9022952256400EE37DF /* RouteProgressTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C36D8FF2952256400EE37DF /* RouteProgressTests.swift */; };
9496
2C4093B5292661FD0099FA0E /* RouteParserSpy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C4093B4292661FD0099FA0E /* RouteParserSpy.swift */; };
9597
2C585157292521C20077A558 /* MapboxCoreNavigation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C5ADFBC91DDCC7840011824B /* MapboxCoreNavigation.framework */; };
9698
2C58515F292523670077A558 /* RouteControllerIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C58515E292523670077A558 /* RouteControllerIntegrationTests.swift */; };
@@ -470,7 +472,6 @@
470472
C51511D120EAC89D00372A91 /* CPMapTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C51511D020EAC89D00372A91 /* CPMapTemplate.swift */; };
471473
C51DF8661F38C31C006C6A15 /* Locale.swift in Sources */ = {isa = PBXBuildFile; fileRef = C51DF8651F38C31C006C6A15 /* Locale.swift */; };
472474
C520EE901EBB84F9008805BC /* Navigation.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C520EE921EBB84F9008805BC /* Navigation.storyboard */; };
473-
C52AC1261DF0E48600396B9F /* RouteProgressTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C52AC1251DF0E48600396B9F /* RouteProgressTests.swift */; };
474475
C53208AB1E81FFB900910266 /* NavigationMapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C53208AA1E81FFB900910266 /* NavigationMapView.swift */; };
475476
C5381F03204E052A00A5493E /* UIDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5381F01204E03B600A5493E /* UIDevice.swift */; };
476477
C53C196D1F38EA25008DB406 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = C53C196F1F38EA25008DB406 /* Localizable.strings */; };
@@ -750,9 +751,11 @@
750751
2C04E46C290A8CA10067FDCF /* PredictiveCacheOptionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PredictiveCacheOptionsTests.swift; sourceTree = "<group>"; };
751752
2C04E46D290A8CA10067FDCF /* PredictiveCacheManagerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PredictiveCacheManagerTests.swift; sourceTree = "<group>"; };
752753
2C257376292B836B00941307 /* ReentrantImageDownloaderSpy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReentrantImageDownloaderSpy.swift; sourceTree = "<group>"; };
753-
2C257378292B8BEB00941307 /* RouteStepProgressTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RouteStepProgressTests.swift; sourceTree = "<group>"; };
754754
2C2880A0291A82630063E5B7 /* RerouteControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RerouteControllerTests.swift; sourceTree = "<group>"; };
755755
2C2880A5291AB7A10063E5B7 /* RerouteDetectorSpy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RerouteDetectorSpy.swift; sourceTree = "<group>"; };
756+
2C36D8FD2952256400EE37DF /* RouteLegProgressTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RouteLegProgressTests.swift; sourceTree = "<group>"; };
757+
2C36D8FE2952256400EE37DF /* RouteStepProgressTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RouteStepProgressTests.swift; sourceTree = "<group>"; };
758+
2C36D8FF2952256400EE37DF /* RouteProgressTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RouteProgressTests.swift; sourceTree = "<group>"; };
756759
2C4093B4292661FD0099FA0E /* RouteParserSpy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RouteParserSpy.swift; sourceTree = "<group>"; };
757760
2C585153292521C20077A558 /* MapboxCoreNavigationIntegrationTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MapboxCoreNavigationIntegrationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
758761
2C58515E292523670077A558 /* RouteControllerIntegrationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RouteControllerIntegrationTests.swift; sourceTree = "<group>"; };
@@ -1155,7 +1158,6 @@
11551158
C51DF8651F38C31C006C6A15 /* Locale.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Locale.swift; sourceTree = "<group>"; };
11561159
C520EE911EBB84F9008805BC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Navigation.storyboard; sourceTree = "<group>"; };
11571160
C520EE941EBBBD55008805BC /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Navigation.strings; sourceTree = "<group>"; };
1158-
C52AC1251DF0E48600396B9F /* RouteProgressTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RouteProgressTests.swift; sourceTree = "<group>"; };
11591161
C53208AA1E81FFB900910266 /* NavigationMapView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = NavigationMapView.swift; sourceTree = "<group>"; };
11601162
C5381F01204E03B600A5493E /* UIDevice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIDevice.swift; sourceTree = "<group>"; };
11611163
C53C19701F38EACD008DB406 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
@@ -1484,6 +1486,16 @@
14841486
path = NavNative;
14851487
sourceTree = "<group>";
14861488
};
1489+
2C36D8FC2952256400EE37DF /* Progress */ = {
1490+
isa = PBXGroup;
1491+
children = (
1492+
2C36D8FD2952256400EE37DF /* RouteLegProgressTests.swift */,
1493+
2C36D8FE2952256400EE37DF /* RouteStepProgressTests.swift */,
1494+
2C36D8FF2952256400EE37DF /* RouteProgressTests.swift */,
1495+
);
1496+
path = Progress;
1497+
sourceTree = "<group>";
1498+
};
14871499
2C585154292521C20077A558 /* MapboxCoreNavigationIntegrationTests */ = {
14881500
isa = PBXGroup;
14891501
children = (
@@ -2385,6 +2397,7 @@
23852397
C5ADFBD61DDCC7840011824B /* MapboxCoreNavigationTests */ = {
23862398
isa = PBXGroup;
23872399
children = (
2400+
2C36D8FC2952256400EE37DF /* Progress */,
23882401
2C9DDBE12934C006007F8CFD /* MapboxCoreNavigationTests.swift */,
23892402
2C9006CD291927B80012CCEA /* MeasurementSystemTests.swift */,
23902403
2C9006CF291927B80012CCEA /* RerouteTests.swift */,
@@ -2403,7 +2416,6 @@
24032416
162039CE216C348500875F5C /* NavigationEventsManagerTests.swift */,
24042417
C551B0E520D42222009A986F /* NavigationLocationManagerTests.swift */,
24052418
C5ABB50D20408D2C00AFA92C /* NavigationServiceTests.swift */,
2406-
C52AC1251DF0E48600396B9F /* RouteProgressTests.swift */,
24072419
C582BA2B2073E77E00647DAA /* StringTests.swift */,
24082420
3597ABCF21553B6F00C12785 /* SimulatedLocationManagerTests.swift */,
24092421
AE8B1B96207D2B2B003050F6 /* TunnelAuthorityTests.swift */,
@@ -2417,7 +2429,6 @@
24172429
8A9270E82704F6CC00B606D9 /* BundleAdditionsTests.swift */,
24182430
E2B4B228272A814600FF0F57 /* ReplayLocationManagerTests.swift */,
24192431
2C2880A0291A82630063E5B7 /* RerouteControllerTests.swift */,
2420-
2C257378292B8BEB00941307 /* RouteStepProgressTests.swift */,
24212432
);
24222433
name = MapboxCoreNavigationTests;
24232434
path = Tests/MapboxCoreNavigationTests;
@@ -3480,8 +3491,9 @@
34803491
2B0C3EE428F6E56600F828DF /* HistoryReaderTests.swift in Sources */,
34813492
E2B4B22A272A814600FF0F57 /* ReplayLocationManagerTests.swift in Sources */,
34823493
E23D8B6B269D7EE90094CEFA /* TilesetDescriptorFactoryTests.swift in Sources */,
3494+
2C36D9002952256400EE37DF /* RouteLegProgressTests.swift in Sources */,
3495+
2C36D9012952256400EE37DF /* RouteStepProgressTests.swift in Sources */,
34833496
359A8AED1FA78D3000BDB486 /* DistanceFormatterTests.swift in Sources */,
3484-
C52AC1261DF0E48600396B9F /* RouteProgressTests.swift in Sources */,
34853497
5A43FC8B24B488DC00BF7943 /* PassiveLocationManagerTests.swift in Sources */,
34863498
2C9DDBE32934C457007F8CFD /* RouteControllerTests.swift in Sources */,
34873499
359574AA1F28CCBB00838209 /* LocationTests.swift in Sources */,
@@ -3493,14 +3505,14 @@
34933505
8A9270EA2704F6CC00B606D9 /* BundleAdditionsTests.swift in Sources */,
34943506
E24CD8202768E36000B6ABBD /* LeakTests.swift in Sources */,
34953507
B426FF0525FFD679001884C8 /* SimulatedLocationManagerTests.swift in Sources */,
3508+
2C36D9022952256400EE37DF /* RouteProgressTests.swift in Sources */,
34963509
35EF782A212C324E001B4BB5 /* TunnelAuthorityTests.swift in Sources */,
34973510
3A163AE0249901C300D66A0D /* RouteStateTests.swift in Sources */,
34983511
C5ABB50E20408D2C00AFA92C /* NavigationServiceTests.swift in Sources */,
34993512
2C193C32290A9BC30050A57F /* PredictiveCacheOptionsTests.swift in Sources */,
35003513
2C9006D7291927D80012CCEA /* RoutesCoordinatorTests.swift in Sources */,
35013514
2C9006D6291927D80012CCEA /* RerouteTests.swift in Sources */,
35023515
11D1F89E269601150053A93F /* NativeHandlersFactoryTests.swift in Sources */,
3503-
2C257379292B8BEC00941307 /* RouteStepProgressTests.swift in Sources */,
35043516
2C193C31290A9BC30050A57F /* PredictiveCacheManagerTests.swift in Sources */,
35053517
);
35063518
runOnlyForDeploymentPostprocessing = 0;

Sources/MapboxCoreNavigation/RouteStepProgress.swift

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,8 @@ open class RouteStepProgress: Codable {
103103
The step must contain `intersectionsIncludingUpcomingManeuverIntersection` otherwise this property will be `nil`.
104104
*/
105105
public var currentIntersection: Intersection? {
106-
guard let intersections = intersectionsIncludingUpcomingManeuverIntersection, intersections.startIndex..<intersections.endIndex ~= intersectionIndex else {
106+
guard let intersections = intersectionsIncludingUpcomingManeuverIntersection,
107+
intersections.indices.contains(intersectionIndex) else {
107108
return nil
108109
}
109110

@@ -131,7 +132,9 @@ open class RouteStepProgress: Codable {
131132
An `Array` of remaining `VisualInstruction` for a step.
132133
*/
133134
public var remainingVisualInstructions: [VisualInstructionBanner]? {
134-
guard let visualInstructions = step.instructionsDisplayedAlongStep else { return nil }
135+
guard let visualInstructions = step.instructionsDisplayedAlongStep,
136+
visualInstructions.indices.contains(visualInstructionIndex) else { return nil }
137+
135138
return Array(visualInstructions.suffix(from: visualInstructionIndex))
136139
}
137140

@@ -144,26 +147,29 @@ open class RouteStepProgress: Codable {
144147
An `Array` of remaining `SpokenInstruction` for a step.
145148
*/
146149
public var remainingSpokenInstructions: [SpokenInstruction]? {
147-
guard let instructions = step.instructionsSpokenAlongStep else { return nil }
148-
guard spokenInstructionIndex < instructions.count else { return nil }
150+
guard let instructions = step.instructionsSpokenAlongStep,
151+
instructions.indices.contains(spokenInstructionIndex) else { return nil }
152+
149153
return Array(instructions.suffix(from: spokenInstructionIndex))
150154
}
151155

152156
/**
153157
Current spoken instruction for the user's progress along a step.
154158
*/
155159
public var currentSpokenInstruction: SpokenInstruction? {
156-
guard let instructionsSpokenAlongStep = step.instructionsSpokenAlongStep else { return nil }
157-
guard spokenInstructionIndex < instructionsSpokenAlongStep.count else { return nil }
160+
guard let instructionsSpokenAlongStep = step.instructionsSpokenAlongStep,
161+
instructionsSpokenAlongStep.indices.contains(spokenInstructionIndex) else { return nil }
162+
158163
return instructionsSpokenAlongStep[spokenInstructionIndex]
159164
}
160165

161166
/**
162167
Current visual instruction for the user's progress along a step.
163168
*/
164169
public var currentVisualInstruction: VisualInstructionBanner? {
165-
guard let instructionsDisplayedAlongStep = step.instructionsDisplayedAlongStep else { return nil }
166-
guard visualInstructionIndex < instructionsDisplayedAlongStep.count else { return nil }
170+
guard let instructionsDisplayedAlongStep = step.instructionsDisplayedAlongStep,
171+
instructionsDisplayedAlongStep.indices.contains(visualInstructionIndex) else { return nil }
172+
167173
return instructionsDisplayedAlongStep[visualInstructionIndex]
168174
}
169175

Sources/MapboxNavigation/InstructionsCardViewController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ open class InstructionsCardViewController: UIViewController {
2626

2727
var mutatedSteps = steps
2828
if mutatedSteps.count > 1 {
29-
mutatedSteps = Array(mutatedSteps.suffix(from: stepIndex))
29+
mutatedSteps = Array(mutatedSteps.dropFirst(stepIndex))
3030
mutatedSteps.removeLast()
3131
}
3232

Sources/MapboxNavigation/Match.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,16 @@ extension Match {
1616
func polylineAroundManeuver(legIndex: Int, stepIndex: Int, distance: CLLocationDistance) -> LineString {
1717
let precedingLegs = legs.prefix(upTo: legIndex)
1818
let precedingLegCoordinates = precedingLegs.flatMap { $0.steps }.flatMap { $0.shape?.coordinates ?? [] }
19-
20-
let precedingSteps = legs[legIndex].steps.prefix(upTo: stepIndex)
19+
20+
let leg = legs[legIndex]
21+
let precedingSteps = leg.steps.prefix(upTo: min(stepIndex, leg.steps.count))
2122
let precedingStepCoordinates = precedingSteps.compactMap { $0.shape?.coordinates }.reduce([], +)
2223
let precedingPolyline = LineString((precedingLegCoordinates + precedingStepCoordinates).reversed())
2324

24-
let followingLegs = legs.suffix(from: legIndex).dropFirst()
25+
let followingLegs = legs.dropFirst(legIndex + 1)
2526
let followingLegCoordinates = followingLegs.flatMap { $0.steps }.flatMap { $0.shape?.coordinates ?? [] }
2627

27-
let followingSteps = legs[legIndex].steps.suffix(from: stepIndex)
28+
let followingSteps = leg.steps.dropFirst(stepIndex)
2829
let followingStepCoordinates = followingSteps.compactMap { $0.shape?.coordinates }.reduce([], +)
2930
let followingPolyline = LineString(followingStepCoordinates + followingLegCoordinates)
3031

@@ -39,7 +40,7 @@ extension Match {
3940
if followingPolyline.coordinates.isEmpty {
4041
return LineString(trimmedPrecedingCoordinates)
4142
} else {
42-
return LineString(trimmedPrecedingCoordinates + followingPolyline.trimmed(from: followingPolyline.coordinates[0], distance: distance)!.coordinates.suffix(from: 1))
43+
return LineString(trimmedPrecedingCoordinates + followingPolyline.trimmed(from: followingPolyline.coordinates[0], distance: distance)!.coordinates.dropFirst())
4344
}
4445
}
4546
}

Sources/MapboxNavigation/NavigationMapView+Annotations.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,8 @@ extension NavigationMapView {
206206
} else {
207207
// We didn't find a previous point that is on-screen so we'll move forward
208208
// through the coordinates looking for one.
209-
for indexedCoordinate in routeShape.coordinates.suffix(from: snappedCoordinate.index) {
209+
let snappedCoordinates = routeShape.coordinates.dropFirst(snappedCoordinate.index)
210+
for indexedCoordinate in snappedCoordinates {
210211
if visibleBoundingBox.contains(indexedCoordinate) {
211212
firstOnscreenCoordinate = indexedCoordinate
212213
break
@@ -456,7 +457,7 @@ extension NavigationMapView {
456457
let intersectionIndex = stepProgress.intersectionIndex
457458
let stepIntersections = stepProgress.intersectionsIncludingUpcomingManeuverIntersection
458459

459-
for intersection in stepIntersections?.suffix(from: intersectionIndex) ?? [] {
460+
for intersection in stepIntersections?.dropFirst(intersectionIndex) ?? [] {
460461
if let feature = intersectionFeature(from: intersection) {
461462
featureCollection.features.append(feature)
462463
}

Sources/MapboxNavigation/NavigationViewportDataSource.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ public class NavigationViewportDataSource: ViewportDataSource {
220220
let nextStepIndex = min(stepIndex + 1, routeProgress.currentLeg.steps.count - 1)
221221

222222
var totalDistance: CLLocationDistance = 0.0
223-
for (index, step) in routeProgress.currentLeg.steps.suffix(from: nextStepIndex).enumerated() {
223+
for (index, step) in routeProgress.currentLeg.steps.dropFirst(nextStepIndex).enumerated() {
224224
guard let stepCoordinates = step.shape?.coordinates,
225225
let distance = stepCoordinates.distance() else { continue }
226226

0 commit comments

Comments
 (0)