From 13f004e2f8a3df7b97d95f2067b4a8ec9d48338a Mon Sep 17 00:00:00 2001 From: Pavan Kumar M Date: Mon, 24 May 2021 00:28:41 +0530 Subject: [PATCH] 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 --- core/java/android/net/NetworkStats.java | 47 ++++++++++++++----------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 6ccbab7ed8..710a8c65ea 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -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.