@Override public TypeProto load(String type) throws Exception { if (type.charAt(0) == '[') { return new ArrayProto(ClassPath.this, type); } else { return new ClassProto(ClassPath.this, type); } } };
private void analyzeAgetWide(@Nonnull AnalyzedInstruction analyzedInstruction) { ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction; RegisterType arrayRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); if (arrayRegisterType.category != RegisterType.NULL) { if (arrayRegisterType.category != RegisterType.REFERENCE || !(arrayRegisterType.type instanceof ArrayProto)) { throw new AnalysisException("aget-wide used with non-array register: %s", arrayRegisterType.toString()); } ArrayProto arrayProto = (ArrayProto)arrayRegisterType.type; if (arrayProto.dimensions != 1) { throw new AnalysisException("aget-wide used with multi-dimensional array: %s", arrayRegisterType.toString()); } char arrayBaseType = arrayProto.getElementType().charAt(0); if (arrayBaseType == 'J') { setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, RegisterType.LONG_LO_TYPE); } else if (arrayBaseType == 'D') { setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, RegisterType.DOUBLE_LO_TYPE); } else { throw new AnalysisException("aget-wide used with narrow array: %s", arrayRegisterType); } } else { // If the array register is null, we can assume that the destination register was meant to be a wide type. // This is the same behavior as dalvik's verifier setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, RegisterType.LONG_LO_TYPE); } }
private void analyzeAgetObject(@Nonnull AnalyzedInstruction analyzedInstruction) { ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction; RegisterType arrayRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); if (arrayRegisterType.category != RegisterType.NULL) { if (arrayRegisterType.category != RegisterType.REFERENCE || !(arrayRegisterType.type instanceof ArrayProto)) { throw new AnalysisException("aget-object used with non-array register: %s", arrayRegisterType.toString()); } ArrayProto arrayProto = (ArrayProto)arrayRegisterType.type; String elementType = arrayProto.getImmediateElementType(); setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, RegisterType.getRegisterType(RegisterType.REFERENCE, classPath.getClass(elementType))); } else { // If the array register is null, we can assume that the destination register was meant to be a reference // type, so we set the destination to NULL. This is the same behavior as dalvik's verifier setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, RegisterType.NULL_TYPE); } }
@Nonnull @Override public TypeProto getCommonSuperclass(@Nonnull TypeProto other) { if (other instanceof ArrayProto) { if (TypeUtils.isPrimitiveType(getElementType()) || TypeUtils.isPrimitiveType(((ArrayProto)other).getElementType())) { if (dimensions == ((ArrayProto)other).dimensions && getElementType().equals(((ArrayProto)other).getElementType())) { return this; return other; return classPath.getClass(makeArrayType(mergedClass.getType(), dimensions)); return classPath.getClass(makeArrayType("Ljava/lang/Object;", dimensions)); try { if (other.isInterface()) { if (implementsInterface(other.getType())) { return other;
@Override public String toString() { return getType(); } @Nonnull @Override public ClassPath getClassPath() { return classPath; }
/** * @return The immediate element type of this array. E.g. This would return [Ljava/lang/String; for * [[Ljava/lang/String; */ @Nonnull public String getImmediateElementType() { if (dimensions > 1) { return makeArrayType(elementType, dimensions-1); } return elementType; }
@Nonnull @Override public TypeProto getCommonSuperclass(@Nonnull TypeProto other) { if (other instanceof ArrayProto) { if (TypeUtils.isPrimitiveType(getElementType()) || TypeUtils.isPrimitiveType(((ArrayProto)other).getElementType())) { if (dimensions == ((ArrayProto)other).dimensions && getElementType().equals(((ArrayProto)other).getElementType())) { return this; return other; return classPath.getClass(makeArrayType(mergedClass.getType(), dimensions)); return classPath.getClass(makeArrayType("Ljava/lang/Object;", dimensions)); try { if (other.isInterface()) { if (implementsInterface(other.getType())) { return other;
@Override public String toString() { return getType(); } @Nonnull @Override public ClassPath getClassPath() { return classPath; }
/** * @return The immediate element type of this array. E.g. This would return [Ljava/lang/String; for * [[Ljava/lang/String; */ @Nonnull public String getImmediateElementType() { if (dimensions > 1) { return makeArrayType(elementType, dimensions-1); } return elementType; }
@Nonnull @Override public TypeProto getCommonSuperclass(@Nonnull TypeProto other) { if (other instanceof ArrayProto) { if (TypeUtils.isPrimitiveType(getElementType()) || TypeUtils.isPrimitiveType(((ArrayProto)other).getElementType())) { if (dimensions == ((ArrayProto)other).dimensions && getElementType().equals(((ArrayProto)other).getElementType())) { return this; return other; return classPath.getClass(makeArrayType(mergedClass.getType(), dimensions)); return classPath.getClass(makeArrayType("Ljava/lang/Object;", dimensions)); try { if (other.isInterface()) { if (implementsInterface(other.getType())) { return other;
@Override public String toString() { return getType(); } @Nonnull @Override public ClassPath getClassPath() { return classPath; }
/** * @return The immediate element type of this array. E.g. This would return [Ljava/lang/String; for * [[Ljava/lang/String; */ @Nonnull public String getImmediateElementType() { if (dimensions > 1) { return makeArrayType(elementType, dimensions-1); } return elementType; }
@Override public TypeProto load(String type) throws Exception { if (type.charAt(0) == '[') { return new ArrayProto(ClassPath.this, type); } else { return new ClassProto(ClassPath.this, type); } } };
private void analyzeAgetObject(@Nonnull AnalyzedInstruction analyzedInstruction) { ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction; RegisterType arrayRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); if (arrayRegisterType.category != RegisterType.NULL) { if (arrayRegisterType.category != RegisterType.REFERENCE || !(arrayRegisterType.type instanceof ArrayProto)) { throw new AnalysisException("aget-object used with non-array register: %s", arrayRegisterType.toString()); } ArrayProto arrayProto = (ArrayProto)arrayRegisterType.type; String elementType = arrayProto.getImmediateElementType(); setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, RegisterType.getRegisterType(RegisterType.REFERENCE, classPath.getClass(elementType))); } else { // If the array register is null, we can assume that the destination register was meant to be a reference // type, so we set the destination to NULL. This is the same behavior as dalvik's verifier setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, RegisterType.NULL_TYPE); } }
private void analyzeAgetWide(@Nonnull AnalyzedInstruction analyzedInstruction) { ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction; RegisterType arrayRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); if (arrayRegisterType.category != RegisterType.NULL) { if (arrayRegisterType.category != RegisterType.REFERENCE || !(arrayRegisterType.type instanceof ArrayProto)) { throw new AnalysisException("aget-wide used with non-array register: %s", arrayRegisterType.toString()); } ArrayProto arrayProto = (ArrayProto)arrayRegisterType.type; if (arrayProto.dimensions != 1) { throw new AnalysisException("aget-wide used with multi-dimensional array: %s", arrayRegisterType.toString()); } char arrayBaseType = arrayProto.getElementType().charAt(0); if (arrayBaseType == 'J') { setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, RegisterType.LONG_LO_TYPE); } else if (arrayBaseType == 'D') { setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, RegisterType.DOUBLE_LO_TYPE); } else { throw new AnalysisException("aget-wide used with narrow array: %s", arrayRegisterType); } } else { // If the array register is null, we can assume that the destination register was meant to be a wide type. // This is the same behavior as dalvik's verifier setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, RegisterType.LONG_LO_TYPE); } }
@Override @Nullable public FieldReference getFieldByOffset(int fieldOffset) { if (fieldOffset==8) { return new ImmutableFieldReference(getType(), "length", "int"); } return null; }
@Nonnull @Override public String getType() { return makeArrayType(elementType, dimensions); } public int getDimensions() { return dimensions; }
@Override public TypeProto load(String type) throws Exception { if (type.charAt(0) == '[') { return new ArrayProto(ClassPath.this, type); } else { return new ClassProto(ClassPath.this, type); } } };
private void analyzeAgetObject(@Nonnull AnalyzedInstruction analyzedInstruction) { ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction; RegisterType arrayRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); if (arrayRegisterType.category != RegisterType.NULL) { if (arrayRegisterType.category != RegisterType.REFERENCE || !(arrayRegisterType.type instanceof ArrayProto)) { throw new AnalysisException("aget-object used with non-array register: %s", arrayRegisterType.toString()); } ArrayProto arrayProto = (ArrayProto)arrayRegisterType.type; String elementType = arrayProto.getImmediateElementType(); setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, RegisterType.getRegisterType(RegisterType.REFERENCE, classPath.getClass(elementType))); } else { // If the array register is null, we can assume that the destination register was meant to be a reference // type, so we set the destination to NULL. This is the same behavior as dalvik's verifier setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, RegisterType.NULL_TYPE); } }
private void analyzeAgetWide(@Nonnull AnalyzedInstruction analyzedInstruction) { ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction; RegisterType arrayRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); if (arrayRegisterType.category != RegisterType.NULL) { if (arrayRegisterType.category != RegisterType.REFERENCE || !(arrayRegisterType.type instanceof ArrayProto)) { throw new AnalysisException("aget-wide used with non-array register: %s", arrayRegisterType.toString()); } ArrayProto arrayProto = (ArrayProto)arrayRegisterType.type; if (arrayProto.dimensions != 1) { throw new AnalysisException("aget-wide used with multi-dimensional array: %s", arrayRegisterType.toString()); } char arrayBaseType = arrayProto.getElementType().charAt(0); if (arrayBaseType == 'J') { setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, RegisterType.LONG_LO_TYPE); } else if (arrayBaseType == 'D') { setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, RegisterType.DOUBLE_LO_TYPE); } else { throw new AnalysisException("aget-wide used with narrow array: %s", arrayRegisterType); } } else { // If the array register is null, we can assume that the destination register was meant to be a wide type. // This is the same behavior as dalvik's verifier setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, RegisterType.LONG_LO_TYPE); } }