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