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