[Retrace] Account for invalid and incorrect signatures
Bug: b/267413327
Change-Id: I5f13f1cd5b20627c42d88c6a9a3fb6456cf62d0e
diff --git a/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java b/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java
index c1dfb81..749f1ea 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java
@@ -389,11 +389,26 @@
MappingInformationDiagnostics.notAllowedCombination(
info, conflictingInfo, lineNo)));
if (info.isResidualSignatureMappingInformation()) {
+ ResidualSignatureMappingInformation mappingInfo =
+ info.asResidualSignatureMappingInformation();
+ if (!mappingInfo.isValid()) {
+ diagnosticsHandler.warning(
+ MappingInformationDiagnostics.invalidResidualSignature(
+ line.trim(), lineNo));
+ return;
+ }
Signature residualSignature =
getResidualSignatureFromMappingInformation(
info.asResidualSignatureMappingInformation(), currentRenamedNameFinal);
currentResidualSignature.set(residualSignature);
if (currentRange != null) {
+ if (!mappingInfo.isResidualMethodSignatureMappingInformation()) {
+ diagnosticsHandler.warning(
+ MappingInformationDiagnostics.invalidResidualSignatureType(
+ info.serialize(), lineNo));
+ currentResidualSignature.clear();
+ return;
+ }
currentRange.setResidualSignatureInternal(
residualSignature.asMethodSignature());
}
@@ -575,7 +590,14 @@
private Signature getResidualSignatureForMemberNaming(
Box<Signature> residualSignature, Signature originalSignature, String renamedName) {
if (residualSignature.isSet()) {
- return residualSignature.get();
+ if (residualSignature.get().getClass() != originalSignature.getClass()) {
+ diagnosticsHandler.warning(
+ MappingInformationDiagnostics.invalidResidualSignatureType(
+ residualSignature.get().toString(), lineNo));
+
+ } else {
+ return residualSignature.get();
+ }
}
Signature signature = originalSignature.asRenamed(renamedName);
signature = signatureCache.computeIfAbsent(signature, Function.identity());
diff --git a/src/main/java/com/android/tools/r8/naming/mappinginformation/MappingInformationDiagnostics.java b/src/main/java/com/android/tools/r8/naming/mappinginformation/MappingInformationDiagnostics.java
index 1c4242a..cc0da51 100644
--- a/src/main/java/com/android/tools/r8/naming/mappinginformation/MappingInformationDiagnostics.java
+++ b/src/main/java/com/android/tools/r8/naming/mappinginformation/MappingInformationDiagnostics.java
@@ -99,4 +99,21 @@
"The mapping '" + one + "' is not allowed in combination with '" + other + "'",
new TextPosition(1, lineNumber, TextPosition.UNKNOWN_COLUMN));
}
+
+ public static MappingInformationDiagnostics invalidResidualSignature(
+ String info, int lineNumber) {
+ return new MappingInformationDiagnostics(
+ "The residual signature mapping '" + info + "' is invalid'",
+ new TextPosition(1, lineNumber, TextPosition.UNKNOWN_COLUMN));
+ }
+
+ public static MappingInformationDiagnostics invalidResidualSignatureType(
+ String info, int lineNumber) {
+ return new MappingInformationDiagnostics(
+ "The residual signature mapping '"
+ + info
+ + "' is not of the same type as the "
+ + "member it describes.'",
+ new TextPosition(1, lineNumber, TextPosition.UNKNOWN_COLUMN));
+ }
}
diff --git a/src/main/java/com/android/tools/r8/naming/mappinginformation/ResidualSignatureMappingInformation.java b/src/main/java/com/android/tools/r8/naming/mappinginformation/ResidualSignatureMappingInformation.java
index 05bbad1..db604e3 100644
--- a/src/main/java/com/android/tools/r8/naming/mappinginformation/ResidualSignatureMappingInformation.java
+++ b/src/main/java/com/android/tools/r8/naming/mappinginformation/ResidualSignatureMappingInformation.java
@@ -63,6 +63,8 @@
}
}
+ public abstract boolean isValid();
+
@Override
public boolean isResidualSignatureMappingInformation() {
return true;
@@ -76,6 +78,9 @@
public static class ResidualMethodSignatureMappingInformation
extends ResidualSignatureMappingInformation {
+ private static final ResidualMethodSignatureMappingInformation INVALID_METHOD_SIGNATURE =
+ new ResidualMethodSignatureMappingInformation(new String[0], "LINVALID;");
+
private final String returnType;
private final String[] parameters;
@@ -93,20 +98,27 @@
parameters, method.getReturnType().toDescriptorString());
}
- public static ResidualFieldSignatureMappingInformation fromDexField(DexField residualField) {
- return new ResidualFieldSignatureMappingInformation(
- residualField.getType().toDescriptorString());
- }
-
@Override
protected String serializeInternal() {
return StringUtils.join("", Arrays.asList(parameters), BraceType.PARENS) + returnType;
}
+ @Override
+ public boolean isValid() {
+ return this != INVALID_METHOD_SIGNATURE;
+ }
+
public static ResidualMethodSignatureMappingInformation deserialize(String signature) {
- return new ResidualMethodSignatureMappingInformation(
- DescriptorUtils.getArgumentTypeDescriptors(signature),
- DescriptorUtils.getReturnTypeDescriptor(signature));
+ String[] argumentTypeDescriptors = DescriptorUtils.getArgumentTypeDescriptors(signature);
+ String returnTypeDescriptor = DescriptorUtils.getReturnTypeDescriptor(signature);
+ boolean isValid = DescriptorUtils.isDescriptor(returnTypeDescriptor);
+ for (String argumentTypeDescriptor : argumentTypeDescriptors) {
+ isValid &= DescriptorUtils.isDescriptor(argumentTypeDescriptor);
+ }
+ return isValid
+ ? new ResidualMethodSignatureMappingInformation(
+ argumentTypeDescriptors, returnTypeDescriptor)
+ : INVALID_METHOD_SIGNATURE;
}
public String getReturnType() {
@@ -148,6 +160,9 @@
public static class ResidualFieldSignatureMappingInformation
extends ResidualSignatureMappingInformation {
+ private static final ResidualFieldSignatureMappingInformation INVALID_FIELD_SIGNATURE =
+ new ResidualFieldSignatureMappingInformation("LINVALID;");
+
private final String type;
private ResidualFieldSignatureMappingInformation(String type) {
@@ -168,8 +183,15 @@
return type;
}
+ @Override
+ public boolean isValid() {
+ return this != INVALID_FIELD_SIGNATURE;
+ }
+
public static ResidualFieldSignatureMappingInformation deserialize(String signature) {
- return new ResidualFieldSignatureMappingInformation(signature);
+ return DescriptorUtils.isDescriptor(signature)
+ ? new ResidualFieldSignatureMappingInformation(signature)
+ : INVALID_FIELD_SIGNATURE;
}
@Override
diff --git a/src/main/java/com/android/tools/r8/utils/positions/MappedPositionToClassNameMapperBuilder.java b/src/main/java/com/android/tools/r8/utils/positions/MappedPositionToClassNameMapperBuilder.java
index b3834cf..7f67d3d 100644
--- a/src/main/java/com/android/tools/r8/utils/positions/MappedPositionToClassNameMapperBuilder.java
+++ b/src/main/java/com/android/tools/r8/utils/positions/MappedPositionToClassNameMapperBuilder.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.utils.positions;
+import static com.android.tools.r8.naming.mappinginformation.ResidualSignatureMappingInformation.ResidualFieldSignatureMappingInformation.fromDexField;
import static com.android.tools.r8.utils.positions.PositionUtils.mustHaveResidualDebugInfo;
import com.android.tools.r8.errors.Unreachable;
@@ -184,9 +185,7 @@
MemberNaming memberNaming = new MemberNaming(originalSignature, residualSignature);
if (ResidualSignatureMappingInformation.isSupported(mapFileVersion)
&& !originalSignature.type.equals(residualSignature.type)) {
- memberNaming.addMappingInformation(
- ResidualMethodSignatureMappingInformation.fromDexField(residualField),
- Unreachable::raise);
+ memberNaming.addMappingInformation(fromDexField(residualField), Unreachable::raise);
}
if (dexEncodedField.isD8R8Synthesized()) {
memberNaming.addMappingInformation(
diff --git a/src/test/java/com/android/tools/r8/retrace/RetraceInvalidResidualSignatureTest.java b/src/test/java/com/android/tools/r8/retrace/RetraceInvalidResidualSignatureTest.java
index 5be9fc2..7663ee1 100644
--- a/src/test/java/com/android/tools/r8/retrace/RetraceInvalidResidualSignatureTest.java
+++ b/src/test/java/com/android/tools/r8/retrace/RetraceInvalidResidualSignatureTest.java
@@ -4,12 +4,14 @@
package com.android.tools.r8.retrace;
-import static org.junit.Assert.assertThrows;
+import static org.hamcrest.CoreMatchers.containsString;
-import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.DiagnosticsMatcher;
import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestDiagnosticMessagesImpl;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.naming.mappinginformation.MappingInformationDiagnostics;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.Reference;
import java.util.Collections;
@@ -44,22 +46,44 @@
+ " # { id:'com.android.tools.r8.residualsignature',signature:'()Ljava/lang/Object;' }\n"
+ " int method1() -> a\n"
+ " # { id:'com.android.tools.r8.residualsignature',signature:'I' }\n"
- + " int method2() -> b\n"
+ + " 1:2:int method2():3:4 -> a\n"
+ + " # { id:'com.android.tools.r8.residualsignature',signature:'Z' }\n"
+ + " int method3() -> b\n"
+ " # { id:'com.android.tools.r8.residualsignature',signature:'VOLAPYK' }\n";
@Test
public void testInvalidResidualMapping() {
- // TODO(b/267413327): Fail more gracefully than just throwing.
- assertThrows(
- AssertionError.class,
- () ->
- Retracer.createDefault(
- ProguardMapProducer.fromString(mapping), new DiagnosticsHandler() {})
- .retraceMethod(
- Reference.method(
- someClassRenamed,
- "method1",
- Collections.emptyList(),
- Reference.primitiveFromDescriptor("I"))));
+ TestDiagnosticMessagesImpl diagnosticsHandler = new TestDiagnosticMessagesImpl();
+ Retracer.createDefault(ProguardMapProducer.fromString(mapping), diagnosticsHandler)
+ .retraceMethod(
+ Reference.method(
+ someClassRenamed,
+ "method1",
+ Collections.emptyList(),
+ Reference.primitiveFromDescriptor("I")));
+ diagnosticsHandler.assertOnlyWarnings();
+ diagnosticsHandler.assertAllWarningsMatch(
+ DiagnosticsMatcher.diagnosticType(MappingInformationDiagnostics.class));
+ diagnosticsHandler.assertWarningsMatch(
+ DiagnosticsMatcher.diagnosticMessage(containsString(getMessage("java.lang.Object a()"))),
+ DiagnosticsMatcher.diagnosticMessage(
+ containsString(
+ getMessage(
+ "{\"id\":\"com.android.tools.r8.residualsignature\",\"signature\":\"I\"}"))),
+ DiagnosticsMatcher.diagnosticMessage(
+ containsString(
+ getMessage(
+ "{\"id\":\"com.android.tools.r8.residualsignature\",\"signature\":\"Z\"}"))),
+ DiagnosticsMatcher.diagnosticMessage(
+ containsString(
+ "The residual signature mapping '# {"
+ + " id:'com.android.tools.r8.residualsignature',signature:'VOLAPYK' }' is"
+ + " invalid")));
+ }
+
+ private String getMessage(String variable) {
+ return "The residual signature mapping '"
+ + variable
+ + "' is not of the same type as the member it describes.";
}
}