• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.dexbacked;
33 
34 import org.jf.util.ExceptionWithContext;
35 import org.jf.util.Utf8Utils;
36 
37 import javax.annotation.Nonnull;
38 
39 public class BaseDexReader<T extends BaseDexBuffer> {
40     @Nonnull public final T dexBuf;
41     private int offset;
42 
BaseDexReader(@onnull T dexBuf, int offset)43     public BaseDexReader(@Nonnull T dexBuf, int offset) {
44         this.dexBuf = dexBuf;
45         this.offset = offset;
46     }
47 
getOffset()48     public int getOffset() { return offset; }
setOffset(int offset)49     public void setOffset(int offset) { this.offset = offset; }
50 
readSleb128()51     public int readSleb128() {
52         int end = dexBuf.baseOffset + offset;
53         int currentByteValue;
54         int result;
55         byte[] buf = dexBuf.buf;
56 
57         result = buf[end++] & 0xff;
58         if (result <= 0x7f) {
59             result = (result << 25) >> 25;
60         } else {
61             currentByteValue = buf[end++] & 0xff;
62             result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7);
63             if (currentByteValue <= 0x7f) {
64                 result = (result << 18) >> 18;
65             } else {
66                 currentByteValue = buf[end++] & 0xff;
67                 result |= (currentByteValue & 0x7f) << 14;
68                 if (currentByteValue <= 0x7f) {
69                     result = (result << 11) >> 11;
70                 } else {
71                     currentByteValue = buf[end++] & 0xff;
72                     result |= (currentByteValue & 0x7f) << 21;
73                     if (currentByteValue <= 0x7f) {
74                         result = (result << 4) >> 4;
75                     } else {
76                         currentByteValue = buf[end++] & 0xff;
77                         if (currentByteValue > 0x7f) {
78                             throw new ExceptionWithContext(
79                                     "Invalid sleb128 integer encountered at offset 0x%x", offset);
80                         }
81                         result |= currentByteValue << 28;
82                     }
83                 }
84             }
85         }
86 
87         offset = end - dexBuf.baseOffset;
88         return result;
89     }
90 
readSmallUleb128()91     public int readSmallUleb128() {
92         return readUleb128(false);
93     }
94 
readUleb128(boolean allowLarge)95     private int readUleb128(boolean allowLarge) {
96         int end = dexBuf.baseOffset + offset;
97         int currentByteValue;
98         int result;
99         byte[] buf = dexBuf.buf;
100 
101         result = buf[end++] & 0xff;
102         if (result > 0x7f) {
103             currentByteValue = buf[end++] & 0xff;
104             result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7);
105             if (currentByteValue > 0x7f) {
106                 currentByteValue = buf[end++] & 0xff;
107                 result |= (currentByteValue & 0x7f) << 14;
108                 if (currentByteValue > 0x7f) {
109                     currentByteValue = buf[end++] & 0xff;
110                     result |= (currentByteValue & 0x7f) << 21;
111                     if (currentByteValue > 0x7f) {
112                         currentByteValue = buf[end++];
113 
114                         // MSB shouldn't be set on last byte
115                         if (currentByteValue < 0) {
116                             throw new ExceptionWithContext(
117                                     "Invalid uleb128 integer encountered at offset 0x%x", offset);
118                         } else if ((currentByteValue & 0xf) > 0x07) {
119                             if (!allowLarge) {
120                                 // for non-large uleb128s, we assume most significant bit of the result will not be
121                                 // set, so that it can fit into a signed integer without wrapping
122                                 throw new ExceptionWithContext(
123                                         "Encountered valid uleb128 that is out of range at offset 0x%x", offset);
124                             }
125                         }
126                         result |= currentByteValue << 28;
127                     }
128                 }
129             }
130         }
131 
132         offset = end - dexBuf.baseOffset;
133         return result;
134     }
135 
136     /**
137      * Reads a "large" uleb128. That is, one that may legitimately be greater than a signed int.
138      *
139      * The value is returned as if it were signed. i.e. a value of 0xFFFFFFFF would be returned as -1. It is up to the
140      * caller to handle the value appropriately.
141      */
readLargeUleb128()142     public int readLargeUleb128() {
143        return readUleb128(true);
144     }
145 
146     /**
147      * Reads a "big" uleb128 that can legitimately be > 2^31. The value is returned as a signed integer, with the
148      * expected semantics of re-interpreting an unsigned value as a signed value.
149      *
150      * @return The unsigned value, reinterpreted as a signed int
151      */
readBigUleb128()152     public int readBigUleb128() {
153         int end = dexBuf.baseOffset + offset;
154         int currentByteValue;
155         int result;
156         byte[] buf = dexBuf.buf;
157 
158         result = buf[end++] & 0xff;
159         if (result > 0x7f) {
160             currentByteValue = buf[end++] & 0xff;
161             result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7);
162             if (currentByteValue > 0x7f) {
163                 currentByteValue = buf[end++] & 0xff;
164                 result |= (currentByteValue & 0x7f) << 14;
165                 if (currentByteValue > 0x7f) {
166                     currentByteValue = buf[end++] & 0xff;
167                     result |= (currentByteValue & 0x7f) << 21;
168                     if (currentByteValue > 0x7f) {
169                         currentByteValue = buf[end++];
170 
171                         // MSB shouldn't be set on last byte
172                         if (currentByteValue < 0) {
173                             throw new ExceptionWithContext(
174                                     "Invalid uleb128 integer encountered at offset 0x%x", offset);
175                         }
176                         result |= currentByteValue << 28;
177                     }
178                 }
179             }
180         }
181 
182         offset = end - dexBuf.baseOffset;
183         return result;
184     }
185 
skipUleb128()186     public void skipUleb128() {
187         int end = dexBuf.baseOffset + offset;
188         byte currentByteValue;
189         byte[] buf = dexBuf.buf;
190 
191         currentByteValue = buf[end++];
192         if (currentByteValue < 0) { // if the MSB is set
193             currentByteValue = buf[end++];
194             if (currentByteValue < 0) { // if the MSB is set
195                 currentByteValue = buf[end++];
196                 if (currentByteValue < 0) { // if the MSB is set
197                     currentByteValue = buf[end++];
198                     if (currentByteValue < 0) { // if the MSB is set
199                         currentByteValue = buf[end++];
200                         if (currentByteValue < 0) {
201                             throw new ExceptionWithContext(
202                                     "Invalid uleb128 integer encountered at offset 0x%x", offset);
203                         }
204                     }
205                 }
206             }
207         }
208 
209         offset = end - dexBuf.baseOffset;
210     }
211 
readSmallUint()212     public int readSmallUint() {
213         int o = offset;
214         int result = dexBuf.readSmallUint(o);
215         offset = o + 4;
216         return result;
217     }
218 
readOptionalUint()219     public int readOptionalUint() {
220         int o = offset;
221         int result = dexBuf.readOptionalUint(o);
222         offset = o + 4;
223         return result;
224     }
225 
peekUshort()226     public int peekUshort() {
227         return dexBuf.readUshort(offset);
228     }
229 
readUshort()230     public int readUshort() {
231         int o = offset;
232         int result = dexBuf.readUshort(offset);
233         offset = o + 2;
234         return result;
235     }
236 
peekUbyte()237     public int peekUbyte() {
238         return dexBuf.readUbyte(offset);
239     }
240 
readUbyte()241     public int readUbyte() {
242         int o = offset;
243         int result = dexBuf.readUbyte(offset);
244         offset = o + 1;
245         return result;
246     }
247 
readLong()248     public long readLong() {
249         int o = offset;
250         long result = dexBuf.readLong(offset);
251         offset = o + 8;
252         return result;
253     }
254 
readInt()255     public int readInt() {
256         int o = offset;
257         int result = dexBuf.readInt(offset);
258         offset = o + 4;
259         return result;
260     }
261 
readShort()262     public int readShort() {
263         int o = offset;
264         int result = dexBuf.readShort(offset);
265         offset = o + 2;
266         return result;
267     }
268 
readByte()269     public int readByte() {
270         int o = offset;
271         int result = dexBuf.readByte(offset);
272         offset = o + 1;
273         return result;
274     }
275 
skipByte()276     public void skipByte() { offset++; }
moveRelative(int i)277     public void moveRelative(int i) { offset += i; }
278 
readSmallUint(int offset)279     public int readSmallUint(int offset) { return dexBuf.readSmallUint(offset); }
readUshort(int offset)280     public int readUshort(int offset) { return dexBuf.readUshort(offset); }
readUbyte(int offset)281     public int readUbyte(int offset) { return dexBuf.readUbyte(offset); }
readLong(int offset)282     public long readLong(int offset) { return dexBuf.readLong(offset); }
readInt(int offset)283     public int readInt(int offset) { return dexBuf.readInt(offset); }
readShort(int offset)284     public int readShort(int offset) { return dexBuf.readShort(offset); }
readByte(int offset)285     public int readByte(int offset) { return dexBuf.readByte(offset); }
286 
readSizedInt(int bytes)287     public int readSizedInt(int bytes) {
288         int o = dexBuf.baseOffset + offset;
289         byte[] buf = dexBuf.buf;
290 
291         int result;
292         switch (bytes) {
293             case 4:
294                 result = (buf[o] & 0xff) |
295                         ((buf[o+1] & 0xff) << 8) |
296                         ((buf[o+2] & 0xff) << 16) |
297                         (buf[o+3] << 24);
298                 break;
299             case 3:
300                 result = (buf[o] & 0xff) |
301                         ((buf[o+1] & 0xff) << 8) |
302                         ((buf[o+2]) << 16);
303                 break;
304             case 2:
305                 result = (buf[o] & 0xff) |
306                         ((buf[o+1]) << 8);
307                 break;
308             case 1:
309                 result = buf[o];
310                 break;
311             default:
312                 throw new ExceptionWithContext("Invalid size %d for sized int at offset 0x%x", bytes, offset);
313         }
314         offset = o + bytes - dexBuf.baseOffset;
315         return result;
316     }
317 
readSizedSmallUint(int bytes)318     public int readSizedSmallUint(int bytes) {
319         int o = dexBuf.baseOffset + offset;
320         byte[] buf = dexBuf.buf;
321 
322         int result = 0;
323         switch (bytes) {
324             case 4:
325                 int b = buf[o+3];
326                 if (b < 0) {
327                     throw new ExceptionWithContext(
328                             "Encountered valid sized uint that is out of range at offset 0x%x", offset);
329                 }
330                 result = b << 24;
331                 // fall-through
332             case 3:
333                 result |= (buf[o+2] & 0xff) << 16;
334                 // fall-through
335             case 2:
336                 result |= (buf[o+1] & 0xff) << 8;
337                 // fall-through
338             case 1:
339                 result |= (buf[o] & 0xff);
340                 break;
341             default:
342                 throw new ExceptionWithContext("Invalid size %d for sized uint at offset 0x%x", bytes, offset);
343         }
344         offset = o + bytes - dexBuf.baseOffset;
345         return result;
346     }
347 
readSizedRightExtendedInt(int bytes)348     public int readSizedRightExtendedInt(int bytes) {
349         int o = dexBuf.baseOffset + offset;
350         byte[] buf = dexBuf.buf;
351 
352         int result;
353         switch (bytes) {
354             case 4:
355                 result = (buf[o] & 0xff) |
356                         ((buf[o+1] & 0xff) << 8) |
357                         ((buf[o+2] & 0xff) << 16) |
358                         (buf[o+3] << 24);
359                 break;
360             case 3:
361                 result = (buf[o] & 0xff) << 8 |
362                         ((buf[o+1] & 0xff) << 16) |
363                         (buf[o+2] << 24);
364                 break;
365             case 2:
366                 result = (buf[o] & 0xff) << 16 |
367                         (buf[o+1] << 24);
368                 break;
369             case 1:
370                 result = buf[o] << 24;
371                 break;
372             default:
373                 throw new ExceptionWithContext(
374                         "Invalid size %d for sized, right extended int at offset 0x%x", bytes, offset);
375         }
376         offset = o + bytes - dexBuf.baseOffset;
377         return result;
378     }
379 
readSizedRightExtendedLong(int bytes)380     public long readSizedRightExtendedLong(int bytes) {
381         int o = dexBuf.baseOffset + offset;
382         byte[] buf = dexBuf.buf;
383 
384         long result;
385         switch (bytes) {
386             case 8:
387                 result = (buf[o] & 0xff) |
388                         ((buf[o+1] & 0xff) << 8) |
389                         ((buf[o+2] & 0xff) << 16) |
390                         ((buf[o+3] & 0xffL) << 24) |
391                         ((buf[o+4] & 0xffL) << 32) |
392                         ((buf[o+5] & 0xffL) << 40) |
393                         ((buf[o+6] & 0xffL) << 48) |
394                         (((long)buf[o+7]) << 56);
395                 break;
396             case 7:
397                 result = ((buf[o] & 0xff)) << 8 |
398                         ((buf[o+1] & 0xff) << 16) |
399                         ((buf[o+2] & 0xffL) << 24) |
400                         ((buf[o+3] & 0xffL) << 32) |
401                         ((buf[o+4] & 0xffL) << 40) |
402                         ((buf[o+5] & 0xffL) << 48) |
403                         (((long)buf[o+6]) << 56);
404                 break;
405             case 6:
406                 result = ((buf[o] & 0xff)) << 16 |
407                         ((buf[o+1] & 0xffL) << 24) |
408                         ((buf[o+2] & 0xffL) << 32) |
409                         ((buf[o+3] & 0xffL) << 40) |
410                         ((buf[o+4] & 0xffL) << 48) |
411                         (((long)buf[o+5]) << 56);
412                 break;
413             case 5:
414                 result = ((buf[o] & 0xffL)) << 24 |
415                         ((buf[o+1] & 0xffL) << 32) |
416                         ((buf[o+2] & 0xffL) << 40) |
417                         ((buf[o+3] & 0xffL) << 48) |
418                         (((long)buf[o+4]) << 56);
419                 break;
420             case 4:
421                 result = ((buf[o] & 0xffL)) << 32 |
422                         ((buf[o+1] & 0xffL) << 40) |
423                         ((buf[o+2] & 0xffL) << 48) |
424                         (((long)buf[o+3]) << 56);
425                 break;
426             case 3:
427                 result = ((buf[o] & 0xffL)) << 40 |
428                         ((buf[o+1] & 0xffL) << 48) |
429                         (((long)buf[o+2]) << 56);
430                 break;
431             case 2:
432                 result = ((buf[o] & 0xffL)) << 48 |
433                         (((long)buf[o+1]) << 56);
434                 break;
435             case 1:
436                 result = ((long)buf[o]) << 56;
437                 break;
438             default:
439                 throw new ExceptionWithContext(
440                         "Invalid size %d for sized, right extended long at offset 0x%x", bytes, offset);
441         }
442         offset = o + bytes - dexBuf.baseOffset;
443         return result;
444     }
445 
readSizedLong(int bytes)446     public long readSizedLong(int bytes) {
447         int o = dexBuf.baseOffset + offset;
448         byte[] buf = dexBuf.buf;
449 
450         long result;
451         switch (bytes) {
452             case 8:
453                 result = (buf[o] & 0xff) |
454                         ((buf[o+1] & 0xff) << 8) |
455                         ((buf[o+2] & 0xff) << 16) |
456                         ((buf[o+3] & 0xffL) << 24) |
457                         ((buf[o+4] & 0xffL) << 32) |
458                         ((buf[o+5] & 0xffL) << 40) |
459                         ((buf[o+6] & 0xffL) << 48) |
460                         (((long)buf[o+7]) << 56);
461                 break;
462             case 7:
463                 result = (buf[o] & 0xff) |
464                         ((buf[o+1] & 0xff) << 8) |
465                         ((buf[o+2] & 0xff) << 16) |
466                         ((buf[o+3] & 0xffL) << 24) |
467                         ((buf[o+4] & 0xffL) << 32) |
468                         ((buf[o+5] & 0xffL) << 40) |
469                         ((long)(buf[o+6]) << 48);
470                 break;
471             case 6:
472                 result = (buf[o] & 0xff) |
473                         ((buf[o+1] & 0xff) << 8) |
474                         ((buf[o+2] & 0xff) << 16) |
475                         ((buf[o+3] & 0xffL) << 24) |
476                         ((buf[o+4] & 0xffL) << 32) |
477                         ((long)(buf[o+5]) << 40);
478                 break;
479             case 5:
480                 result = (buf[o] & 0xff) |
481                         ((buf[o+1] & 0xff) << 8) |
482                         ((buf[o+2] & 0xff) << 16) |
483                         ((buf[o+3] & 0xffL) << 24) |
484                         ((long)(buf[o+4]) << 32);
485                 break;
486             case 4:
487                 result = (buf[o] & 0xff) |
488                         ((buf[o+1] & 0xff) << 8) |
489                         ((buf[o+2] & 0xff) << 16) |
490                         (((long)buf[o+3]) << 24);
491                 break;
492             case 3:
493                 result = (buf[o] & 0xff) |
494                         ((buf[o+1] & 0xff) << 8) |
495                         (buf[o+2] << 16);
496                 break;
497             case 2:
498                 result = (buf[o] & 0xff) |
499                         (buf[o+1] << 8);
500                 break;
501             case 1:
502                 result = buf[o];
503                 break;
504             default:
505                 throw new ExceptionWithContext("Invalid size %d for sized long at offset 0x%x", bytes, offset);
506         }
507 
508         offset = o + bytes - dexBuf.baseOffset;
509         return result;
510     }
511 
readString(int utf16Length)512     public String readString(int utf16Length) {
513         int[] ret = new int[1];
514         String value = Utf8Utils.utf8BytesWithUtf16LengthToString(
515                 dexBuf.buf, dexBuf.baseOffset + offset, utf16Length, ret);
516         offset += ret[0];
517         return value;
518     }
519 }
520