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 check35cRegisterCount(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 check25xParameterRegisterCount(int registerCount) {
    137         if (registerCount < 0 || registerCount > 4) {
    138             throw new IllegalArgumentException(
    139                     String.format("Invalid parameter register count: %d. " +
    140                             "Must be between 0 and 4, inclusive.", registerCount));
    141         }
    142         return registerCount;
    143     }
    144 
    145     public static int checkRegisterRangeCount(int registerCount) {
    146         if ((registerCount & 0xFFFFFF00) != 0) {
    147             throw new IllegalArgumentException(
    148                     String.format("Invalid register count: %d. Must be between 0 and 255, inclusive.", registerCount));
    149         }
    150         return registerCount;
    151     }
    152 
    153     public static void checkValueArg(int valueArg, int maxValue) {
    154         if (valueArg > maxValue) {
    155             if (maxValue == 0) {
    156                 throw new IllegalArgumentException(
    157                         String.format("Invalid value_arg value %d for an encoded_value. Expecting 0",
    158                                 valueArg));
    159             }
    160             throw new IllegalArgumentException(
    161                     String.format("Invalid value_arg value %d for an encoded_value. Expecting 0..%d, inclusive",
    162                             valueArg, maxValue));
    163         }
    164     }
    165 
    166     public static int checkFieldOffset(int fieldOffset) {
    167         if (fieldOffset < 0 || fieldOffset > 65535) {
    168             throw new IllegalArgumentException(
    169                     String.format("Invalid field offset: 0x%x. Must be between 0x0000 and 0xFFFF inclusive",
    170                             fieldOffset));
    171         }
    172         return fieldOffset;
    173     }
    174 
    175     public static int checkVtableIndex(int vtableIndex) {
    176         if (vtableIndex < 0 || vtableIndex > 65535) {
    177             throw new IllegalArgumentException(
    178                     String.format("Invalid vtable index: %d. Must be between 0 and 65535, inclusive", vtableIndex));
    179         }
    180         return vtableIndex;
    181     }
    182 
    183     public static int checkInlineIndex(int inlineIndex) {
    184         if (inlineIndex < 0 || inlineIndex > 65535) {
    185             throw new IllegalArgumentException(
    186                     String.format("Invalid inline index: %d. Must be between 0 and 65535, inclusive", inlineIndex));
    187         }
    188         return inlineIndex;
    189     }
    190 
    191     public static int checkVerificationError(int verificationError) {
    192         if (!VerificationError.isValidVerificationError(verificationError)) {
    193             throw new IllegalArgumentException(
    194                     String.format("Invalid verification error value: %d. Must be between 1 and 9, inclusive",
    195                             verificationError));
    196         }
    197         return verificationError;
    198     }
    199 
    200     public static <T extends Reference> T checkReference(int referenceType, T reference) {
    201         switch (referenceType) {
    202             case ReferenceType.STRING:
    203                 if (!(reference instanceof StringReference)) {
    204                     throw new IllegalArgumentException("Invalid reference type, expecting a string reference");
    205                 }
    206                 break;
    207             case ReferenceType.TYPE:
    208                 if (!(reference instanceof TypeReference)) {
    209                     throw new IllegalArgumentException("Invalid reference type, expecting a type reference");
    210                 }
    211                 break;
    212             case ReferenceType.FIELD:
    213                 if (!(reference instanceof FieldReference)) {
    214                     throw new IllegalArgumentException("Invalid reference type, expecting a field reference");
    215                 }
    216                 break;
    217             case ReferenceType.METHOD:
    218                 if (!(reference instanceof MethodReference)) {
    219                     throw new IllegalArgumentException("Invalid reference type, expecting a method reference");
    220                 }
    221                 break;
    222             default:
    223                 throw new IllegalArgumentException(String.format("Not a valid reference type: %d", referenceType));
    224         }
    225         return reference;
    226     }
    227 }
    228