From 8f9fb34f2d53beb22ad9055eb071a93157b922ba Mon Sep 17 00:00:00 2001 From: Yohann Roussel Date: Mon, 9 Mar 2015 17:59:10 +0100 Subject: Descriptor references are direct references We have to parse descriptors and treat the types they reference as direct reference as we do for other direct type references. This is required because Dalvik verifier is checking those descriptor the same way as it does for other type references. See: https://android.googlesource.com/platform/dalvik/+/kitkat-mr2.2-release/vm/analysis/CodeVerify.cpp#637 Bug: 19626444 Change-Id: Ibdc8c3c129148994b3b28882db1c2ec38e9bbea8 --- .../multidex/ClassReferenceListBuilder.java | 44 +++++++++++++++------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/dx/src/com/android/multidex/ClassReferenceListBuilder.java b/dx/src/com/android/multidex/ClassReferenceListBuilder.java index 0434cad98..8218693c9 100644 --- a/dx/src/com/android/multidex/ClassReferenceListBuilder.java +++ b/dx/src/com/android/multidex/ClassReferenceListBuilder.java @@ -19,7 +19,11 @@ package com.android.multidex; import com.android.dx.cf.direct.DirectClassFile; import com.android.dx.rop.cst.Constant; import com.android.dx.rop.cst.ConstantPool; +import com.android.dx.rop.cst.CstFieldRef; +import com.android.dx.rop.cst.CstMethodRef; import com.android.dx.rop.cst.CstType; +import com.android.dx.rop.type.Prototype; +import com.android.dx.rop.type.StdTypeList; import com.android.dx.rop.type.Type; import com.android.dx.rop.type.TypeList; @@ -37,8 +41,8 @@ import java.util.zip.ZipFile; public class ClassReferenceListBuilder { private static final String CLASS_EXTENSION = ".class"; - private Path path; - private Set classNames = new HashSet(); + private final Path path; + private final Set classNames = new HashSet(); public ClassReferenceListBuilder(Path path) { this.path = path; @@ -96,23 +100,35 @@ public class ClassReferenceListBuilder { private void addDependencies(ConstantPool pool) { for (Constant constant : pool.getEntries()) { if (constant instanceof CstType) { - Type type = ((CstType) constant).getClassType(); - String descriptor = type.getDescriptor(); - if (descriptor.endsWith(";")) { - int lastBrace = descriptor.lastIndexOf('['); - if (lastBrace < 0) { - addClassWithHierachy(descriptor.substring(1, descriptor.length()-1)); - } else { - assert descriptor.length() > lastBrace + 3 - && descriptor.charAt(lastBrace + 1) == 'L'; - addClassWithHierachy(descriptor.substring(lastBrace + 2, - descriptor.length() - 1)); - } + checkDescriptor(((CstType) constant).getClassType()); + } else if (constant instanceof CstFieldRef) { + checkDescriptor(((CstFieldRef) constant).getType()); + } else if (constant instanceof CstMethodRef) { + Prototype proto = ((CstMethodRef) constant).getPrototype(); + checkDescriptor(proto.getReturnType()); + StdTypeList args = proto.getParameterTypes(); + for (int i = 0; i < args.size(); i++) { + checkDescriptor(args.get(i)); } } } } + private void checkDescriptor(Type type) { + String descriptor = type.getDescriptor(); + if (descriptor.endsWith(";")) { + int lastBrace = descriptor.lastIndexOf('['); + if (lastBrace < 0) { + addClassWithHierachy(descriptor.substring(1, descriptor.length()-1)); + } else { + assert descriptor.length() > lastBrace + 3 + && descriptor.charAt(lastBrace + 1) == 'L'; + addClassWithHierachy(descriptor.substring(lastBrace + 2, + descriptor.length() - 1)); + } + } + } + private void addClassWithHierachy(String classBinaryName) { if (classNames.contains(classBinaryName)) { return; -- cgit v1.2.3