Gracefully handle integer overflows.

Avoid recording negative data by doing integer-based
math as much as possible, but switch to double-based
math if we detect that we'd end up causing an overflow.

Test :
    - Builds, Boots
    - High data throughput scenarios
    - NetworkStatsHistoryTest, NetworkStatsCollectionTest,
      NetworkStatsTest

Bug: 119527458
Change-Id: I355fc9bd127da83c1dc70ab3b1261346d4fa5de0
This commit is contained in:
Pavan Kumar M
2021-05-24 00:28:41 +05:30
parent 5c20637731
commit 13f004e2f8

View File

@@ -16,6 +16,8 @@
package android.net;
import static com.android.internal.net.NetworkUtilsInternal.multiplySafeByRational;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -1553,32 +1555,37 @@ public final class NetworkStats implements Parcelable {
// processes this every time device has transmitted/received amount equivalent to
// global threshold alert (~ 2MB) across all interfaces.
final long rxBytesAcrossUnderlyingIfaces =
underlyingIfacesTotal.rxBytes * rxBytes[i] / tunIfaceTotal.rxBytes;
multiplySafeByRational(underlyingIfacesTotal.rxBytes,
rxBytes[i], tunIfaceTotal.rxBytes);
// app must not be blamed for more than it consumed on tunIface
totalRxBytes = Math.min(rxBytes[i], rxBytesAcrossUnderlyingIfaces);
}
long totalRxPackets = 0;
if (tunIfaceTotal.rxPackets > 0) {
final long rxPacketsAcrossUnderlyingIfaces =
underlyingIfacesTotal.rxPackets * rxPackets[i] / tunIfaceTotal.rxPackets;
multiplySafeByRational(underlyingIfacesTotal.rxPackets,
rxPackets[i], tunIfaceTotal.rxPackets);
totalRxPackets = Math.min(rxPackets[i], rxPacketsAcrossUnderlyingIfaces);
}
long totalTxBytes = 0;
if (tunIfaceTotal.txBytes > 0) {
final long txBytesAcrossUnderlyingIfaces =
underlyingIfacesTotal.txBytes * txBytes[i] / tunIfaceTotal.txBytes;
multiplySafeByRational(underlyingIfacesTotal.txBytes,
txBytes[i], tunIfaceTotal.txBytes);
totalTxBytes = Math.min(txBytes[i], txBytesAcrossUnderlyingIfaces);
}
long totalTxPackets = 0;
if (tunIfaceTotal.txPackets > 0) {
final long txPacketsAcrossUnderlyingIfaces =
underlyingIfacesTotal.txPackets * txPackets[i] / tunIfaceTotal.txPackets;
multiplySafeByRational(underlyingIfacesTotal.txPackets,
txPackets[i], tunIfaceTotal.txPackets);
totalTxPackets = Math.min(txPackets[i], txPacketsAcrossUnderlyingIfaces);
}
long totalOperations = 0;
if (tunIfaceTotal.operations > 0) {
final long operationsAcrossUnderlyingIfaces =
underlyingIfacesTotal.operations * operations[i] / tunIfaceTotal.operations;
multiplySafeByRational(underlyingIfacesTotal.operations,
operations[i], tunIfaceTotal.operations);
totalOperations = Math.min(operations[i], operationsAcrossUnderlyingIfaces);
}
// In a second pass, distribute these values across interfaces in the proportion that
@@ -1590,37 +1597,37 @@ public final class NetworkStats implements Parcelable {
tmpEntry.set = set[i];
if (underlyingIfacesTotal.rxBytes > 0) {
tmpEntry.rxBytes =
totalRxBytes
* perInterfaceTotal[j].rxBytes
/ underlyingIfacesTotal.rxBytes;
multiplySafeByRational(totalRxBytes,
perInterfaceTotal[j].rxBytes,
underlyingIfacesTotal.rxBytes);
}
tmpEntry.rxPackets = 0;
if (underlyingIfacesTotal.rxPackets > 0) {
tmpEntry.rxPackets =
totalRxPackets
* perInterfaceTotal[j].rxPackets
/ underlyingIfacesTotal.rxPackets;
multiplySafeByRational(totalRxPackets,
perInterfaceTotal[j].rxPackets,
underlyingIfacesTotal.rxPackets);
}
tmpEntry.txBytes = 0;
if (underlyingIfacesTotal.txBytes > 0) {
tmpEntry.txBytes =
totalTxBytes
* perInterfaceTotal[j].txBytes
/ underlyingIfacesTotal.txBytes;
multiplySafeByRational(totalTxBytes,
perInterfaceTotal[j].txBytes,
underlyingIfacesTotal.txBytes);
}
tmpEntry.txPackets = 0;
if (underlyingIfacesTotal.txPackets > 0) {
tmpEntry.txPackets =
totalTxPackets
* perInterfaceTotal[j].txPackets
/ underlyingIfacesTotal.txPackets;
multiplySafeByRational(totalTxPackets,
perInterfaceTotal[j].txPackets,
underlyingIfacesTotal.txPackets);
}
tmpEntry.operations = 0;
if (underlyingIfacesTotal.operations > 0) {
tmpEntry.operations =
totalOperations
* perInterfaceTotal[j].operations
/ underlyingIfacesTotal.operations;
multiplySafeByRational(totalOperations,
perInterfaceTotal[j].operations,
underlyingIfacesTotal.operations);
}
// tmpEntry now contains the migrated data of the i-th entry for the j-th underlying
// interface. Add that data usage to this object.