Fix overflow in R8 stats metadata
Fixes: b/436805211
Change-Id: I66af37e7c3998597f0317d3736815c210dbe79b4
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
index fee3104..36c3a0a 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -48,6 +48,7 @@
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.metadata.impl.BuildMetadataFactory;
+import com.android.tools.r8.metadata.impl.R8StatsMetadataImpl;
import com.android.tools.r8.naming.KotlinModuleSynthesizer;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.naming.ProguardMapSupplier.ProguardMapId;
@@ -723,6 +724,8 @@
assert appView.hasClassHierarchy();
options.r8BuildMetadataConsumer.accept(
BuildMetadataFactory.create(appView.withClassHierarchy(), virtualFiles));
+ } else if (appView.hasClassHierarchy()) {
+ assert R8StatsMetadataImpl.Counters.create(appView.withClassHierarchy()).validate();
}
}
diff --git a/src/main/java/com/android/tools/r8/metadata/impl/R8StatsMetadataImpl.java b/src/main/java/com/android/tools/r8/metadata/impl/R8StatsMetadataImpl.java
index 05b8e2f..4928feb 100644
--- a/src/main/java/com/android/tools/r8/metadata/impl/R8StatsMetadataImpl.java
+++ b/src/main/java/com/android/tools/r8/metadata/impl/R8StatsMetadataImpl.java
@@ -70,7 +70,7 @@
return noShrinkingPercentage;
}
- private static class Counters {
+ public static class Counters {
private int itemsCount = 0;
private int noObfuscationCount = 0;
@@ -79,12 +79,13 @@
private Counters() {}
- static Counters create(AppView<? extends AppInfoWithClassHierarchy> appView) {
+ public static Counters create(AppView<? extends AppInfoWithClassHierarchy> appView) {
Counters counters = new Counters();
for (DexProgramClass clazz : appView.appInfo().classes()) {
counters.add(appView, clazz);
clazz.forEachProgramMember(member -> counters.add(appView, member));
}
+ assert counters.validate();
return counters;
}
@@ -111,9 +112,34 @@
}
float toPercentageWithTwoDecimals(int count) {
- // Multiply by 100 twice to get percentage with two decimals.
- float number = (float) (count * 100 * 100) / itemsCount;
- return (float) Math.round(number) / 100;
+ if (itemsCount == 0) {
+ return 0f;
+ }
+ float fraction = (float) count / itemsCount;
+ assert verifyValidFraction(fraction);
+ float percentage = fraction * 100;
+ assert verifyValidPercentage(percentage);
+ // Multiply and divide by 100 to get percentage with two decimals.
+ return (float) Math.round(percentage * 100) / 100;
+ }
+
+ public boolean validate() {
+ assert verifyValidPercentage(getNoObfuscationPercentage());
+ assert verifyValidPercentage(getNoOptimizationPercentage());
+ assert verifyValidPercentage(getNoShrinkingPercentage());
+ return true;
+ }
+
+ private boolean verifyValidFraction(float f) {
+ assert 0f <= f;
+ assert f <= 1f;
+ return true;
+ }
+
+ private boolean verifyValidPercentage(float f) {
+ assert 0f <= f;
+ assert f <= 100f;
+ return true;
}
}
}