Home | History | Annotate | Download | only in libdex
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /*
     18  * Functions for interpreting LEB128 (little endian base 128) values
     19  */
     20 
     21 #ifndef LIBDEX_LEB128_H_
     22 #define LIBDEX_LEB128_H_
     23 
     24 #include "DexFile.h"
     25 
     26 /*
     27  * Reads an unsigned LEB128 value, updating the given pointer to point
     28  * just past the end of the read value. This function tolerates
     29  * non-zero high-order bits in the fifth encoded byte.
     30  */
     31 DEX_INLINE int readUnsignedLeb128(const u1** pStream) {
     32     const u1* ptr = *pStream;
     33     int result = *(ptr++);
     34 
     35     if (result > 0x7f) {
     36         int cur = *(ptr++);
     37         result = (result & 0x7f) | ((cur & 0x7f) << 7);
     38         if (cur > 0x7f) {
     39             cur = *(ptr++);
     40             result |= (cur & 0x7f) << 14;
     41             if (cur > 0x7f) {
     42                 cur = *(ptr++);
     43                 result |= (cur & 0x7f) << 21;
     44                 if (cur > 0x7f) {
     45                     /*
     46                      * Note: We don't check to see if cur is out of
     47                      * range here, meaning we tolerate garbage in the
     48                      * high four-order bits.
     49                      */
     50                     cur = *(ptr++);
     51                     result |= cur << 28;
     52                 }
     53             }
     54         }
     55     }
     56 
     57     *pStream = ptr;
     58     return result;
     59 }
     60 
     61 /*
     62  * Reads a signed LEB128 value, updating the given pointer to point
     63  * just past the end of the read value. This function tolerates
     64  * non-zero high-order bits in the fifth encoded byte.
     65  */
     66 DEX_INLINE int readSignedLeb128(const u1** pStream) {
     67     const u1* ptr = *pStream;
     68     int result = *(ptr++);
     69 
     70     if (result <= 0x7f) {
     71         result = (result << 25) >> 25;
     72     } else {
     73         int cur = *(ptr++);
     74         result = (result & 0x7f) | ((cur & 0x7f) << 7);
     75         if (cur <= 0x7f) {
     76             result = (result << 18) >> 18;
     77         } else {
     78             cur = *(ptr++);
     79             result |= (cur & 0x7f) << 14;
     80             if (cur <= 0x7f) {
     81                 result = (result << 11) >> 11;
     82             } else {
     83                 cur = *(ptr++);
     84                 result |= (cur & 0x7f) << 21;
     85                 if (cur <= 0x7f) {
     86                     result = (result << 4) >> 4;
     87                 } else {
     88                     /*
     89                      * Note: We don't check to see if cur is out of
     90                      * range here, meaning we tolerate garbage in the
     91                      * high four-order bits.
     92                      */
     93                     cur = *(ptr++);
     94                     result |= cur << 28;
     95                 }
     96             }
     97         }
     98     }
     99 
    100     *pStream = ptr;
    101     return result;
    102 }
    103 
    104 /*
    105  * Reads an unsigned LEB128 value, updating the given pointer to point
    106  * just past the end of the read value and also indicating whether the
    107  * value was syntactically valid. The only syntactically *invalid*
    108  * values are ones that are five bytes long where the final byte has
    109  * any but the low-order four bits set. Additionally, if the limit is
    110  * passed as non-NULL and bytes would need to be read past the limit,
    111  * then the read is considered invalid.
    112  */
    113 int readAndVerifyUnsignedLeb128(const u1** pStream, const u1* limit,
    114         bool* okay);
    115 
    116 /*
    117  * Reads a signed LEB128 value, updating the given pointer to point
    118  * just past the end of the read value and also indicating whether the
    119  * value was syntactically valid. The only syntactically *invalid*
    120  * values are ones that are five bytes long where the final byte has
    121  * any but the low-order four bits set. Additionally, if the limit is
    122  * passed as non-NULL and bytes would need to be read past the limit,
    123  * then the read is considered invalid.
    124  */
    125 int readAndVerifySignedLeb128(const u1** pStream, const u1* limit, bool* okay);
    126 
    127 
    128 /*
    129  * Writes a 32-bit value in unsigned ULEB128 format.
    130  *
    131  * Returns the updated pointer.
    132  */
    133 DEX_INLINE u1* writeUnsignedLeb128(u1* ptr, u4 data)
    134 {
    135     while (true) {
    136         u1 out = data & 0x7f;
    137         if (out != data) {
    138             *ptr++ = out | 0x80;
    139             data >>= 7;
    140         } else {
    141             *ptr++ = out;
    142             break;
    143         }
    144     }
    145 
    146     return ptr;
    147 }
    148 
    149 /*
    150  * Returns the number of bytes needed to encode "val" in ULEB128 form.
    151  */
    152 DEX_INLINE int unsignedLeb128Size(u4 data)
    153 {
    154     int count = 0;
    155 
    156     do {
    157         data >>= 7;
    158         count++;
    159     } while (data != 0);
    160 
    161     return count;
    162 }
    163 
    164 #endif
    165