Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright 2012, Google Inc.
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are
      7  * met:
      8  *
      9  *     * Redistributions of source code must retain the above copyright
     10  * notice, this list of conditions and the following disclaimer.
     11  *     * Redistributions in binary form must reproduce the above
     12  * copyright notice, this list of conditions and the following disclaimer
     13  * in the documentation and/or other materials provided with the
     14  * distribution.
     15  *     * Neither the name of Google Inc. nor the names of its
     16  * contributors may be used to endorse or promote products derived from
     17  * this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 package org.jf.dexlib2.util;
     33 
     34 import org.jf.dexlib2.Format;
     35 import org.jf.dexlib2.Opcode;
     36 import org.jf.dexlib2.ReferenceType;
     37 import org.jf.dexlib2.VerificationError;
     38 import org.jf.dexlib2.iface.reference.*;
     39 
     40 public class Preconditions {
     41     public static void checkFormat(Opcode opcode, Format expectedFormat) {
     42         if (opcode.format != expectedFormat) {
     43             throw new IllegalArgumentException(
     44                     String.format("Invalid opcode %s for %s", opcode.name, expectedFormat.name()));
     45         }
     46     }
     47 
     48     public static int checkNibbleRegister(int register) {
     49         if ((register & 0xFFFFFFF0) != 0) {
     50             throw new IllegalArgumentException(
     51                     String.format("Invalid register: v%d. Must be between v0 and v15, inclusive.", register));
     52         }
     53         return register;
     54     }
     55 
     56     public static int checkByteRegister(int register) {
     57         if ((register & 0xFFFFFF00) != 0) {
     58             throw new IllegalArgumentException(
     59                     String.format("Invalid register: v%d. Must be between v0 and v255, inclusive.", register));
     60         }
     61         return register;
     62     }
     63 
     64     public static int checkShortRegister(int register) {
     65         if ((register & 0xFFFF0000) != 0) {
     66             throw new IllegalArgumentException(
     67                     String.format("Invalid register: v%d. Must be between v0 and v65535, inclusive.", register));
     68         }
     69         return register;
     70     }
     71 
     72     public static int checkNibbleLiteral(int literal) {
     73         if (literal < -8 || literal > 7) {
     74             throw new IllegalArgumentException(
     75                     String.format("Invalid literal value: %d. Must be between -8 and 7, inclusive.", literal));
     76         }
     77         return literal;
     78     }
     79 
     80     public static int checkByteLiteral(int literal) {
     81         if (literal < -128 || literal > 127) {
     82             throw new IllegalArgumentException(
     83                     String.format("Invalid literal value: %d. Must be between -128 and 127, inclusive.", literal));
     84         }
     85         return literal;
     86     }
     87 
     88     public static int checkShortLiteral(int literal) {
     89         if (literal < -32768 || literal > 32767) {
     90             throw new IllegalArgumentException(
     91                     String.format("Invalid literal value: %d. Must be between -32768 and 32767, inclusive.", literal));
     92         }
     93         return literal;
     94     }
     95 
     96     public static int checkIntegerHatLiteral(int literal) {
     97         if ((literal & 0xFFFF) != 0) {
     98             throw new IllegalArgumentException(
     99                     String.format("Invalid literal value: %d. Low 16 bits must be zeroed out.", literal));
    100         }
    101         return literal;
    102     }
    103 
    104     public static long checkLongHatLiteral(long literal) {
    105         if ((literal & 0xFFFFFFFFFFFFL) != 0) {
    106             throw new IllegalArgumentException(
    107                     String.format("Invalid literal value: %d. Low 48 bits must be zeroed out.", literal));
    108         }
    109         return literal;
    110     }
    111 
    112     public static int checkByteCodeOffset(int offset) {
    113         if (offset < -128 || offset > 127) {
    114             throw new IllegalArgumentException(
    115                     String.format("Invalid code offset: %d. Must be between -128 and 127, inclusive.", offset));
    116         }
    117         return offset;
    118     }
    119 
    120     public static int checkShortCodeOffset(int offset) {
    121         if (offset < -32768 || offset > 32767) {
    122             throw new IllegalArgumentException(
    123                     String.format("Invalid code offset: %d. Must be between -32768 and 32767, inclusive.", offset));
    124         }
    125         return offset;
    126     }
    127 
    128     public static int check35cAnd45ccRegisterCount(int registerCount) {
    129         if (registerCount < 0 || registerCount > 5) {
    130             throw new IllegalArgumentException(
    131                     String.format("Invalid register count: %d. Must be between 0 and 5, inclusive.", registerCount));
    132         }
    133         return registerCount;
    134     }
    135 
    136     public static int checkRegisterRangeCount(int registerCount) {
    137         if ((registerCount & 0xFFFFFF00) != 0) {
    138             throw new IllegalArgumentException(
    139                     String.format("Invalid register count: %d. Must be between 0 and 255, inclusive.", registerCount));
    140         }
    141         return registerCount;
    142     }
    143 
    144     public static void checkValueArg(int valueArg, int maxValue) {
    145         if (valueArg > maxValue) {
    146             if (maxValue == 0) {
    147                 throw new IllegalArgumentException(
    148                         String.format("Invalid value_arg value %d for an encoded_value. Expecting 0",
    149                                 valueArg));
    150             }
    151             throw new IllegalArgumentException(
    152                     String.format("Invalid value_arg value %d for an encoded_value. Expecting 0..%d, inclusive",
    153                             valueArg, maxValue));
    154         }
    155     }
    156 
    157     public static int checkFieldOffset(int fieldOffset) {
    158         if (fieldOffset < 0 || fieldOffset > 65535) {
    159             throw new IllegalArgumentException(
    160                     String.format("Invalid field offset: 0x%x. Must be between 0x0000 and 0xFFFF inclusive",
    161                             fieldOffset));
    162         }
    163         return fieldOffset;
    164     }
    165 
    166     public static int checkVtableIndex(int vtableIndex) {
    167         if (vtableIndex < 0 || vtableIndex > 65535) {
    168             throw new IllegalArgumentException(
    169                     String.format("Invalid vtable index: %d. Must be between 0 and 65535, inclusive", vtableIndex));
    170         }
    171         return vtableIndex;
    172     }
    173 
    174     public static int checkInlineIndex(int inlineIndex) {
    175         if (inlineIndex < 0 || inlineIndex > 65535) {
    176             throw new IllegalArgumentException(
    177                     String.format("Invalid inline index: %d. Must be between 0 and 65535, inclusive", inlineIndex));
    178         }
    179         return inlineIndex;
    180     }
    181 
    182     public static int checkVerificationError(int verificationError) {
    183         if (!VerificationError.isValidVerificationError(verificationError)) {
    184             throw new IllegalArgumentException(
    185                     String.format("Invalid verification error value: %d. Must be between 1 and 9, inclusive",
    186                             verificationError));
    187         }
    188         return verificationError;
    189     }
    190 
    191     public static <T extends Reference> T checkReference(int referenceType, T reference) {
    192         switch (referenceType) {
    193             case ReferenceType.STRING:
    194                 if (!(reference instanceof StringReference)) {
    195                     throw new IllegalArgumentException("Invalid reference type, expecting a string reference");
    196                 }
    197                 break;
    198             case ReferenceType.TYPE:
    199                 if (!(reference instanceof TypeReference)) {
    200                     throw new IllegalArgumentException("Invalid reference type, expecting a type reference");
    201                 }
    202                 break;
    203             case ReferenceType.FIELD:
    204                 if (!(reference instanceof FieldReference)) {
    205                     throw new IllegalArgumentException("Invalid reference type, expecting a field reference");
    206                 }
    207                 break;
    208             case ReferenceType.METHOD:
    209                 if (!(reference instanceof MethodReference)) {
    210                     throw new IllegalArgumentException("Invalid reference type, expecting a method reference");
    211                 }
    212                 break;
    213             default:
    214                 throw new IllegalArgumentException(String.format("Not a valid reference type: %d", referenceType));
    215         }
    216         return reference;
    217     }
    218 }
    219