Skip to content

Commit

Permalink
Fix a division-by-zero crash in the VPN code (#823)
Browse files Browse the repository at this point in the history
Task/Issue URL: https://app.asana.com/0/1203137811378537/1207299387361586/f

iOS PR: duckduckgo/iOS#2862
macOS PR: duckduckgo/macos-browser#2785
What kind of version bump will this require?: Patch

## Description

Fixes a crash caused by a division by zero.
  • Loading branch information
diegoreymendez authored May 17, 2024
1 parent 7d5ddc9 commit ada5f68
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import Common
/// This class was designed to be easy to modify to eventually handle more than two snapshots over time.
///
final class NetworkProtectionConnectionBandwidthAnalyzer {
private struct Snapshot {
struct Snapshot {
let rxBytes: UInt64
let txBytes: UInt64
let date: Date
Expand Down Expand Up @@ -86,7 +86,7 @@ final class NetworkProtectionConnectionBandwidthAnalyzer {
return
}

let (rx, tx) = bytesPerSecond(newer: newer, older: older)
let (rx, tx) = Self.bytesPerSecond(newer: newer, older: older)

os_log("Bytes per second in last time-interval: (rx: %{public}@, tx: %{public}@)",
log: .networkProtectionBandwidthAnalysis,
Expand All @@ -109,10 +109,18 @@ final class NetworkProtectionConnectionBandwidthAnalyzer {

// MARK: - Delta Calculation

private func bytesPerSecond(newer: Snapshot, older: Snapshot) -> (rx: Double, tx: Double) {
let deltaSeconds = newer.date.timeIntervalSince1970 - older.date.timeIntervalSince1970
let rx = Double(newer.rxBytes - older.rxBytes) / deltaSeconds
let tx = Double(newer.txBytes - older.txBytes) / deltaSeconds
static func bytesPerSecond(newer: Snapshot, older: Snapshot) -> (rx: Double, tx: Double) {
let deltaSeconds = newer.date.timeIntervalSince(older.date)
let rx: Double
let tx: Double

if deltaSeconds > 0 {
rx = Double(newer.rxBytes - older.rxBytes) / deltaSeconds
tx = Double(newer.txBytes - older.txBytes) / deltaSeconds
} else {
rx = 0
tx = 0
}

return (rx, tx)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//
// NetworkProtectionConnectionBandwidthAnalyzerTests.swift
//
// Copyright © 2024 DuckDuckGo. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import Foundation
import XCTest
@testable import NetworkProtection
@testable import NetworkProtectionTestUtils

final class NetworkProtectionConnectionBandwidthAnalyzerTests: XCTestCase {

func testBytesPerSecondCalculationIsCorrect() {
let deltaSeconds = TimeInterval(5)
let oldDate = Date()
let newDate = oldDate.addingTimeInterval(deltaSeconds)
let oldRx = UInt64(1000)
let newRx = UInt64(2000)
let oldTx = UInt64(2000)
let newTx = UInt64(6000)
let expectedRx = Double(newRx - oldRx) / deltaSeconds
let expectedTx = Double(newTx - oldTx) / deltaSeconds

let oldSnapshot = NetworkProtectionConnectionBandwidthAnalyzer.Snapshot(rxBytes: oldRx, txBytes: oldTx, date: oldDate)
let newSnapshot = NetworkProtectionConnectionBandwidthAnalyzer.Snapshot(rxBytes: newRx, txBytes: newTx, date: newDate)

let (rx, tx) = NetworkProtectionConnectionBandwidthAnalyzer.bytesPerSecond(newer: newSnapshot, older: oldSnapshot)

XCTAssertEqual(rx, expectedRx)
XCTAssertEqual(tx, expectedTx)
}

func testBytesPerSecondNoTimeDelta() {
let deltaSeconds = TimeInterval(0)
let oldDate = Date()
let newDate = oldDate.addingTimeInterval(deltaSeconds)
let oldRx = UInt64(1000)
let newRx = UInt64(2000)
let oldTx = UInt64(2000)
let newTx = UInt64(6000)
let expectedRx = Double(0)
let expectedTx = Double(0)

let oldSnapshot = NetworkProtectionConnectionBandwidthAnalyzer.Snapshot(rxBytes: oldRx, txBytes: oldTx, date: oldDate)
let newSnapshot = NetworkProtectionConnectionBandwidthAnalyzer.Snapshot(rxBytes: newRx, txBytes: newTx, date: newDate)

let (rx, tx) = NetworkProtectionConnectionBandwidthAnalyzer.bytesPerSecond(newer: newSnapshot, older: oldSnapshot)

XCTAssertEqual(rx, expectedRx)
XCTAssertEqual(tx, expectedTx)
}
}

0 comments on commit ada5f68

Please sign in to comment.