private String getMethodProtoTypeStr(MethodId methodId) { StringBuilder strBuilder = new StringBuilder(); strBuilder.append(owner.strings().get(methodId.nameIndex)); ProtoId protoId = owner.protoIds().get(methodId.protoIndex); strBuilder.append('('); short[] paramTypeIds = owner.parameterTypeIndicesFromMethodId(methodId); for (short typeId : paramTypeIds) { strBuilder.append(owner.typeNames().get(typeId)); } strBuilder.append(')').append(owner.typeNames().get(protoId.returnTypeIndex)); return strBuilder.toString(); } }
private boolean isTypeIdsChangeAffectedToReferrer( Dex oldDex, Dex newDex, short[] oldTypeIds, short[] newTypeIds, boolean compareNameOnly ) { if (oldTypeIds.length != newTypeIds.length) { return true; } int typeIdCount = oldTypeIds.length; for (int i = 0; i < typeIdCount; ++i) { if (compareNameOnly) { String oldTypeName = oldDex.typeNames().get(oldTypeIds[i]); String newTypeName = newDex.typeNames().get(newTypeIds[i]); if (!oldTypeName.equals(newTypeName)) { return true; } } else { if (isTypeChangeAffectedToReferrer(oldDex, newDex, oldTypeIds[i], newTypeIds[i])) { return true; } } } return false; }
public Set<DexClassInfo> getClassInfosInDexesWithDuplicateCheck() { Map<String, DexClassInfo> classDescToInfoMap = new HashMap<>(); for (Dex dex : dexes) { int classDefIndex = 0; for (ClassDef classDef : dex.classDefs()) { String classDesc = dex.typeNames().get(classDef.typeIndex); if (!classDescToInfoMap.containsKey(classDesc)) { classDescToInfoMap.put(classDesc, new DexClassInfo(classDesc, classDefIndex, classDef, dex)); ++classDefIndex; } else { throw new IllegalStateException( String.format( "duplicate class descriptor [%s] in different dexes.", classDesc ) ); } } } return new HashSet<>(classDescToInfoMap.values()); } }
private boolean isTypeChangeAffectedToReferrer( Dex oldDex, Dex newDex, int oldTypeId, int newTypeId ) { if (oldTypeId != ClassDef.NO_INDEX && newTypeId != ClassDef.NO_INDEX) { String oldClassDesc = oldDex.typeNames().get(oldTypeId); String newClassDesc = newDex.typeNames().get(newTypeId); if (!oldClassDesc.equals(newClassDesc)) { return true; } final DexClassInfo oldClassInfo = oldClassDescriptorToClassInfoMap.get(oldClassDesc); final DexClassInfo newClassInfo = newClassDescriptorToClassInfoMap.get(newClassDesc); ClassDef oldClassDef = (oldClassInfo != null ? oldClassInfo.classDef : null); ClassDef newClassDef = (newClassInfo != null ? newClassInfo.classDef : null); if (oldClassDef != null && newClassDef != null) { return isClassChangeAffectedToReferrer(oldClassInfo.owner, newClassInfo.owner, oldClassDef, newClassDef); } else if (oldClassDef == null && newClassDef == null) { return false; } else { // If current comparing class is ignored, since it must be removed // in patched dexes as we expected, here we ignore this kind of changes. return !Utils.isStringMatchesPatterns(oldClassDesc, patternsOfIgnoredRemovedClassDesc); } } else { if (!(oldTypeId == ClassDef.NO_INDEX && newTypeId == ClassDef.NO_INDEX)) { return true; } } return false; }
switch (indexType) { case InstructionCodec.INDEX_TYPE_TYPE_REF: { typeName = owner.typeNames().get(index); refInfoInLog = "init referrer-affected class"; break; typeName = owner.typeNames().get(fieldId.declaringClassIndex); refInfoInLog = "referencing to field: " + owner.strings().get(fieldId.nameIndex); break; typeName = owner.typeNames().get(methodId.declaringClassIndex); refInfoInLog = "invoking method: " + getMethodProtoTypeStr(methodId); break; "Method %s in class %s referenced referrer-affected class %s by %s", getMethodProtoTypeStr(methodId), owner.typeNames().get(methodId.declaringClassIndex), typeName, refInfoInLog
int classDefIndex = 0; for (ClassDef oldClassDef : oldDex.classDefs()) { String desc = oldDex.typeNames().get(oldClassDef.typeIndex); if (Utils.isStringMatchesPatterns(desc, patternsOfClassDescToCheck)) { if (!oldDescriptorOfClassesToCheck.add(desc)) { int classDefIndex = 0; for (ClassDef newClassDef : newDex.classDefs()) { String desc = newDex.typeNames().get(newClassDef.typeIndex); if (Utils.isStringMatchesPatterns(desc, patternsOfClassDescToCheck)) { if (!newDescriptorOfClassesToCheck.add(desc)) {
boolean result = false; String classDesc = oldDex.typeNames().get(oldClassDef.typeIndex);
oldClassesDescToCheck.clear(); for (ClassDef classDef : oldDex.classDefs()) { String desc = oldDex.typeNames().get(classDef.typeIndex); if (Utils.isStringMatchesPatterns(desc, patternsOfClassDescToCheck)) { oldClassesDescToCheck.add(desc); newClassesDescToCheck.clear(); for (ClassDef classDef : newDex.classDefs()) { String desc = newDex.typeNames().get(classDef.typeIndex); if (Utils.isStringMatchesPatterns(desc, patternsOfClassDescToCheck)) { newClassesDescToCheck.add(desc);
List<Integer> offsetOfClassDatasToRemove = new ArrayList<>(classNamePatternCount); for (ClassDef classDef : this.newDex.classDefs()) { String typeName = this.newDex.typeNames().get(classDef.typeIndex); for (Pattern pattern : classNamePatterns) { if (pattern.matcher(typeName).matches()) {
private String getMethodProtoTypeStr(MethodId methodId) { StringBuilder strBuilder = new StringBuilder(); strBuilder.append(owner.strings().get(methodId.nameIndex)); ProtoId protoId = owner.protoIds().get(methodId.protoIndex); strBuilder.append('('); short[] paramTypeIds = owner.parameterTypeIndicesFromMethodId(methodId); for (short typeId : paramTypeIds) { strBuilder.append(owner.typeNames().get(typeId)); } strBuilder.append(')').append(owner.typeNames().get(protoId.returnTypeIndex)); return strBuilder.toString(); } }
private boolean isTypeIdsChangeAffectedToReferrer( Dex oldDex, Dex newDex, short[] oldTypeIds, short[] newTypeIds, boolean compareNameOnly ) { if (oldTypeIds.length != newTypeIds.length) { return true; } int typeIdCount = oldTypeIds.length; for (int i = 0; i < typeIdCount; ++i) { if (compareNameOnly) { String oldTypeName = oldDex.typeNames().get(oldTypeIds[i]); String newTypeName = newDex.typeNames().get(newTypeIds[i]); if (!oldTypeName.equals(newTypeName)) { return true; } } else { if (isTypeChangeAffectedToReferrer(oldDex, newDex, oldTypeIds[i], newTypeIds[i])) { return true; } } } return false; }
public Set<DexClassInfo> getClassInfosInDexesWithDuplicateCheck() { Map<String, DexClassInfo> classDescToInfoMap = new HashMap<>(); for (Dex dex : dexes) { int classDefIndex = 0; for (ClassDef classDef : dex.classDefs()) { String classDesc = dex.typeNames().get(classDef.typeIndex); if (!classDescToInfoMap.containsKey(classDesc)) { classDescToInfoMap.put(classDesc, new DexClassInfo(classDesc, classDefIndex, classDef, dex)); ++classDefIndex; } else { throw new IllegalStateException( String.format( "duplicate class descriptor [%s] in different dexes.", classDesc ) ); } } } return new HashSet<>(classDescToInfoMap.values()); } }
private boolean isTypeChangeAffectedToReferrer( Dex oldDex, Dex newDex, int oldTypeId, int newTypeId ) { if (oldTypeId != ClassDef.NO_INDEX && newTypeId != ClassDef.NO_INDEX) { String oldClassDesc = oldDex.typeNames().get(oldTypeId); String newClassDesc = newDex.typeNames().get(newTypeId); if (!oldClassDesc.equals(newClassDesc)) { return true; } final DexClassInfo oldClassInfo = oldClassDescriptorToClassInfoMap.get(oldClassDesc); final DexClassInfo newClassInfo = newClassDescriptorToClassInfoMap.get(newClassDesc); ClassDef oldClassDef = (oldClassInfo != null ? oldClassInfo.classDef : null); ClassDef newClassDef = (newClassInfo != null ? newClassInfo.classDef : null); if (oldClassDef != null && newClassDef != null) { return isClassChangeAffectedToReferrer(oldClassInfo.owner, newClassInfo.owner, oldClassDef, newClassDef); } else if (oldClassDef == null && newClassDef == null) { return false; } else { // If current comparing class is ignored, since it must be removed // in patched dexes as we expected, here we ignore this kind of changes. return !Utils.isStringMatchesPatterns(oldClassDesc, patternsOfIgnoredRemovedClassDesc); } } else { if (!(oldTypeId == ClassDef.NO_INDEX && newTypeId == ClassDef.NO_INDEX)) { return true; } } return false; }
switch (indexType) { case InstructionCodec.INDEX_TYPE_TYPE_REF: { typeName = owner.typeNames().get(index); refInfoInLog = "init referrer-affected class"; break; typeName = owner.typeNames().get(fieldId.declaringClassIndex); refInfoInLog = "referencing to field: " + owner.strings().get(fieldId.nameIndex); break; typeName = owner.typeNames().get(methodId.declaringClassIndex); refInfoInLog = "invoking method: " + getMethodProtoTypeStr(methodId); break; "Method %s in class %s referenced referrer-affected class %s by %s", getMethodProtoTypeStr(methodId), owner.typeNames().get(methodId.declaringClassIndex), typeName, refInfoInLog