• 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 
peekSleb128Size()91     public int peekSleb128Size() {
92         int end = dexBuf.baseOffset + offset;
93         int currentByteValue;
94         int result;
95         byte[] buf = dexBuf.buf;
96 
97         result = buf[end++] & 0xff;
98         if (result > 0x7f) {
99             currentByteValue = buf[end++] & 0xff;
100             if (currentByteValue > 0x7f) {
101                 currentByteValue = buf[end++] & 0xff;
102                 if (currentByteValue > 0x7f) {
103                     currentByteValue = buf[end++] & 0xff;
104                     if (currentByteValue > 0x7f) {
105                         currentByteValue = buf[end++] & 0xff;
106                         if (currentByteValue > 0x7f) {
107                             throw new ExceptionWithContext(
108                                 "Invalid sleb128 integer encountered at offset 0x%x", offset);
109                         }
110                     }
111                 }
112             }
113         }
114 
115         return end - (dexBuf.baseOffset + offset);
116     }
117 
readSmallUleb128()118     public int readSmallUleb128() {
119         return readUleb128(false);
120     }
121 
peekSmallUleb128Size()122     public int peekSmallUleb128Size() {
123         return peekUleb128Size(false);
124     }
125 
readUleb128(boolean allowLarge)126     private int readUleb128(boolean allowLarge) {
127         int end = dexBuf.baseOffset + offset;
128         int currentByteValue;
129         int result;
130         byte[] buf = dexBuf.buf;
131 
132         result = buf[end++] & 0xff;
133         if (result > 0x7f) {
134             currentByteValue = buf[end++] & 0xff;
135             result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7);
136             if (currentByteValue > 0x7f) {
137                 currentByteValue = buf[end++] & 0xff;
138                 result |= (currentByteValue & 0x7f) << 14;
139                 if (currentByteValue > 0x7f) {
140                     currentByteValue = buf[end++] & 0xff;
141                     result |= (currentByteValue & 0x7f) << 21;
142                     if (currentByteValue > 0x7f) {
143                         currentByteValue = buf[end++];
144 
145                         // MSB shouldn't be set on last byte
146                         if (currentByteValue < 0) {
147                             throw new ExceptionWithContext(
148                                     "Invalid uleb128 integer encountered at offset 0x%x", offset);
149                         } else if ((currentByteValue & 0xf) > 0x07) {
150                             if (!allowLarge) {
151                                 // for non-large uleb128s, we assume most significant bit of the result will not be
152                                 // set, so that it can fit into a signed integer without wrapping
153                                 throw new ExceptionWithContext(
154                                         "Encountered valid uleb128 that is out of range at offset 0x%x", offset);
155                             }
156                         }
157                         result |= currentByteValue << 28;
158                     }
159                 }
160             }
161         }
162 
163         offset = end - dexBuf.baseOffset;
164         return result;
165     }
166 
peekUleb128Size(boolean allowLarge)167     private int peekUleb128Size(boolean allowLarge) {
168         int end = dexBuf.baseOffset + offset;
169         int currentByteValue;
170         int result;
171         byte[] buf = dexBuf.buf;
172 
173         result = buf[end++] & 0xff;
174         if (result > 0x7f) {
175             currentByteValue = buf[end++] & 0xff;
176             if (currentByteValue > 0x7f) {
177                 currentByteValue = buf[end++] & 0xff;
178                 if (currentByteValue > 0x7f) {
179                     currentByteValue = buf[end++] & 0xff;
180                     if (currentByteValue > 0x7f) {
181                         currentByteValue = buf[end++];
182 
183                         // MSB shouldn't be set on last byte
184                         if (currentByteValue < 0) {
185                             throw new ExceptionWithContext(
186                                 "Invalid uleb128 integer encountered at offset 0x%x", offset);
187                         } else if ((currentByteValue & 0xf) > 0x07) {
188                             if (!allowLarge) {
189                                 // for non-large uleb128s, we assume most significant bit of the result will not be
190                                 // set, so that it can fit into a signed integer without wrapping
191                                 throw new ExceptionWithContext(
192                                     "Encountered valid uleb128 that is out of range at offset 0x%x", offset);
193                             }
194                         }
195                     }
196                 }
197             }
198         }
199 
200         return end - (dexBuf.baseOffset + offset);
201     }
202 
203 
204     /**
205      * Reads a "large" uleb128. That is, one that may legitimately be greater than a signed int.
206      *
207      * 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
208      * caller to handle the value appropriately.
209      */
readLargeUleb128()210     public int readLargeUleb128() {
211        return readUleb128(true);
212     }
213 
214     /**
215      * Reads a "big" uleb128 that can legitimately be > 2^31. The value is returned as a signed integer, with the
216      * expected semantics of re-interpreting an unsigned value as a signed value.
217      *
218      * @return The unsigned value, reinterpreted as a signed int
219      */
readBigUleb128()220     public int readBigUleb128() {
221         int end = dexBuf.baseOffset + offset;
222         int currentByteValue;
223         int result;
224         byte[] buf = dexBuf.buf;
225 
226         result = buf[end++] & 0xff;
227         if (result > 0x7f) {
228             currentByteValue = buf[end++] & 0xff;
229             result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7);
230             if (currentByteValue > 0x7f) {
231                 currentByteValue = buf[end++] & 0xff;
232                 result |= (currentByteValue & 0x7f) << 14;
233                 if (currentByteValue > 0x7f) {
234                     currentByteValue = buf[end++] & 0xff;
235                     result |= (currentByteValue & 0x7f) << 21;
236                     if (currentByteValue > 0x7f) {
237                         currentByteValue = buf[end++];
238 
239                         // MSB shouldn't be set on last byte
240                         if (currentByteValue < 0) {
241                             throw new ExceptionWithContext(
242                                     "Invalid uleb128 integer encountered at offset 0x%x", offset);
243                         }
244                         result |= currentByteValue << 28;
245                     }
246                 }
247             }
248         }
249 
250         offset = end - dexBuf.baseOffset;
251         return result;
252     }
253 
peekBigUleb128Size()254     public int peekBigUleb128Size() {
255         int end = dexBuf.baseOffset + offset;
256         int currentByteValue;
257         int result;
258         byte[] buf = dexBuf.buf;
259 
260         result = buf[end++] & 0xff;
261         if (result > 0x7f) {
262             currentByteValue = buf[end++] & 0xff;
263             if (currentByteValue > 0x7f) {
264                 currentByteValue = buf[end++] & 0xff;
265                 if (currentByteValue > 0x7f) {
266                     currentByteValue = buf[end++] & 0xff;
267                     if (currentByteValue > 0x7f) {
268                         currentByteValue = buf[end++];
269 
270                         // MSB shouldn't be set on last byte
271                         if (currentByteValue < 0) {
272                             throw new ExceptionWithContext(
273                                 "Invalid uleb128 integer encountered at offset 0x%x", offset);
274                         }
275                     }
276                 }
277             }
278         }
279 
280         return end - (dexBuf.baseOffset + offset);
281     }
282 
skipUleb128()283     public void skipUleb128() {
284         int end = dexBuf.baseOffset + offset;
285         byte currentByteValue;
286         byte[] buf = dexBuf.buf;
287 
288         currentByteValue = buf[end++];
289         if (currentByteValue < 0) { // if the MSB is set
290             currentByteValue = buf[end++];
291             if (currentByteValue < 0) { // if the MSB is set
292                 currentByteValue = buf[end++];
293                 if (currentByteValue < 0) { // if the MSB is set
294                     currentByteValue = buf[end++];
295                     if (currentByteValue < 0) { // if the MSB is set
296                         currentByteValue = buf[end++];
297                         if (currentByteValue < 0) {
298                             throw new ExceptionWithContext(
299                                     "Invalid uleb128 integer encountered at offset 0x%x", offset);
300                         }
301                     }
302                 }
303             }
304         }
305 
306         offset = end - dexBuf.baseOffset;
307     }
308 
readSmallUint()309     public int readSmallUint() {
310         int o = offset;
311         int result = dexBuf.readSmallUint(o);
312         offset = o + 4;
313         return result;
314     }
315 
readOptionalUint()316     public int readOptionalUint() {
317         int o = offset;
318         int result = dexBuf.readOptionalUint(o);
319         offset = o + 4;
320         return result;
321     }
322 
peekUshort()323     public int peekUshort() {
324         return dexBuf.readUshort(offset);
325     }
326 
readUshort()327     public int readUshort() {
328         int o = offset;
329         int result = dexBuf.readUshort(offset);
330         offset = o + 2;
331         return result;
332     }
333 
peekUbyte()334     public int peekUbyte() {
335         return dexBuf.readUbyte(offset);
336     }
337 
readUbyte()338     public int readUbyte() {
339         int o = offset;
340         int result = dexBuf.readUbyte(offset);
341         offset = o + 1;
342         return result;
343     }
344 
readLong()345     public long readLong() {
346         int o = offset;
347         long result = dexBuf.readLong(offset);
348         offset = o + 8;
349         return result;
350     }
351 
readInt()352     public int readInt() {
353         int o = offset;
354         int result = dexBuf.readInt(offset);
355         offset = o + 4;
356         return result;
357     }
358 
readShort()359     public int readShort() {
360         int o = offset;
361         int result = dexBuf.readShort(offset);
362         offset = o + 2;
363         return result;
364     }
365 
readByte()366     public int readByte() {
367         int o = offset;
368         int result = dexBuf.readByte(offset);
369         offset = o + 1;
370         return result;
371     }
372 
skipByte()373     public void skipByte() { offset++; }
moveRelative(int i)374     public void moveRelative(int i) { offset += i; }
375 
readSmallUint(int offset)376     public int readSmallUint(int offset) { return dexBuf.readSmallUint(offset); }
readUshort(int offset)377     public int readUshort(int offset) { return dexBuf.readUshort(offset); }
readUbyte(int offset)378     public int readUbyte(int offset) { return dexBuf.readUbyte(offset); }
readLong(int offset)379     public long readLong(int offset) { return dexBuf.readLong(offset); }
readInt(int offset)380     public int readInt(int offset) { return dexBuf.readInt(offset); }
readShort(int offset)381     public int readShort(int offset) { return dexBuf.readShort(offset); }
readByte(int offset)382     public int readByte(int offset) { return dexBuf.readByte(offset); }
383 
readSizedInt(int bytes)384     public int readSizedInt(int bytes) {
385         int o = dexBuf.baseOffset + offset;
386         byte[] buf = dexBuf.buf;
387 
388         int result;
389         switch (bytes) {
390             case 4:
391                 result = (buf[o] & 0xff) |
392                         ((buf[o+1] & 0xff) << 8) |
393                         ((buf[o+2] & 0xff) << 16) |
394                         (buf[o+3] << 24);
395                 break;
396             case 3:
397                 result = (buf[o] & 0xff) |
398                         ((buf[o+1] & 0xff) << 8) |
399                         ((buf[o+2]) << 16);
400                 break;
401             case 2:
402                 result = (buf[o] & 0xff) |
403                         ((buf[o+1]) << 8);
404                 break;
405             case 1:
406                 result = buf[o];
407                 break;
408             default:
409                 throw new ExceptionWithContext("Invalid size %d for sized int at offset 0x%x", bytes, offset);
410         }
411         offset = o + bytes - dexBuf.baseOffset;
412         return result;
413     }
414 
readSizedSmallUint(int bytes)415     public int readSizedSmallUint(int bytes) {
416         int o = dexBuf.baseOffset + offset;
417         byte[] buf = dexBuf.buf;
418 
419         int result = 0;
420         switch (bytes) {
421             case 4:
422                 int b = buf[o+3];
423                 if (b < 0) {
424                     throw new ExceptionWithContext(
425                             "Encountered valid sized uint that is out of range at offset 0x%x", offset);
426                 }
427                 result = b << 24;
428                 // fall-through
429             case 3:
430                 result |= (buf[o+2] & 0xff) << 16;
431                 // fall-through
432             case 2:
433                 result |= (buf[o+1] & 0xff) << 8;
434                 // fall-through
435             case 1:
436                 result |= (buf[o] & 0xff);
437                 break;
438             default:
439                 throw new ExceptionWithContext("Invalid size %d for sized uint at offset 0x%x", bytes, offset);
440         }
441         offset = o + bytes - dexBuf.baseOffset;
442         return result;
443     }
444 
readSizedRightExtendedInt(int bytes)445     public int readSizedRightExtendedInt(int bytes) {
446         int o = dexBuf.baseOffset + offset;
447         byte[] buf = dexBuf.buf;
448 
449         int result;
450         switch (bytes) {
451             case 4:
452                 result = (buf[o] & 0xff) |
453                         ((buf[o+1] & 0xff) << 8) |
454                         ((buf[o+2] & 0xff) << 16) |
455                         (buf[o+3] << 24);
456                 break;
457             case 3:
458                 result = (buf[o] & 0xff) << 8 |
459                         ((buf[o+1] & 0xff) << 16) |
460                         (buf[o+2] << 24);
461                 break;
462             case 2:
463                 result = (buf[o] & 0xff) << 16 |
464                         (buf[o+1] << 24);
465                 break;
466             case 1:
467                 result = buf[o] << 24;
468                 break;
469             default:
470                 throw new ExceptionWithContext(
471                         "Invalid size %d for sized, right extended int at offset 0x%x", bytes, offset);
472         }
473         offset = o + bytes - dexBuf.baseOffset;
474         return result;
475     }
476 
readSizedRightExtendedLong(int bytes)477     public long readSizedRightExtendedLong(int bytes) {
478         int o = dexBuf.baseOffset + offset;
479         byte[] buf = dexBuf.buf;
480 
481         long result;
482         switch (bytes) {
483             case 8:
484                 result = (buf[o] & 0xff) |
485                         ((buf[o+1] & 0xff) << 8) |
486                         ((buf[o+2] & 0xff) << 16) |
487                         ((buf[o+3] & 0xffL) << 24) |
488                         ((buf[o+4] & 0xffL) << 32) |
489                         ((buf[o+5] & 0xffL) << 40) |
490                         ((buf[o+6] & 0xffL) << 48) |
491                         (((long)buf[o+7]) << 56);
492                 break;
493             case 7:
494                 result = ((buf[o] & 0xff)) << 8 |
495                         ((buf[o+1] & 0xff) << 16) |
496                         ((buf[o+2] & 0xffL) << 24) |
497                         ((buf[o+3] & 0xffL) << 32) |
498                         ((buf[o+4] & 0xffL) << 40) |
499                         ((buf[o+5] & 0xffL) << 48) |
500                         (((long)buf[o+6]) << 56);
501                 break;
502             case 6:
503                 result = ((buf[o] & 0xff)) << 16 |
504                         ((buf[o+1] & 0xffL) << 24) |
505                         ((buf[o+2] & 0xffL) << 32) |
506                         ((buf[o+3] & 0xffL) << 40) |
507                         ((buf[o+4] & 0xffL) << 48) |
508                         (((long)buf[o+5]) << 56);
509                 break;
510             case 5:
511                 result = ((buf[o] & 0xffL)) << 24 |
512                         ((buf[o+1] & 0xffL) << 32) |
513                         ((buf[o+2] & 0xffL) << 40) |
514                         ((buf[o+3] & 0xffL) << 48) |
515                         (((long)buf[o+4]) << 56);
516                 break;
517             case 4:
518                 result = ((buf[o] & 0xffL)) << 32 |
519                         ((buf[o+1] & 0xffL) << 40) |
520                         ((buf[o+2] & 0xffL) << 48) |
521                         (((long)buf[o+3]) << 56);
522                 break;
523             case 3:
524                 result = ((buf[o] & 0xffL)) << 40 |
525                         ((buf[o+1] & 0xffL) << 48) |
526                         (((long)buf[o+2]) << 56);
527                 break;
528             case 2:
529                 result = ((buf[o] & 0xffL)) << 48 |
530                         (((long)buf[o+1]) << 56);
531                 break;
532             case 1:
533                 result = ((long)buf[o]) << 56;
534                 break;
535             default:
536                 throw new ExceptionWithContext(
537                         "Invalid size %d for sized, right extended long at offset 0x%x", bytes, offset);
538         }
539         offset = o + bytes - dexBuf.baseOffset;
540         return result;
541     }
542 
readSizedLong(int bytes)543     public long readSizedLong(int bytes) {
544         int o = dexBuf.baseOffset + offset;
545         byte[] buf = dexBuf.buf;
546 
547         long result;
548         switch (bytes) {
549             case 8:
550                 result = (buf[o] & 0xff) |
551                         ((buf[o+1] & 0xff) << 8) |
552                         ((buf[o+2] & 0xff) << 16) |
553                         ((buf[o+3] & 0xffL) << 24) |
554                         ((buf[o+4] & 0xffL) << 32) |
555                         ((buf[o+5] & 0xffL) << 40) |
556                         ((buf[o+6] & 0xffL) << 48) |
557                         (((long)buf[o+7]) << 56);
558                 break;
559             case 7:
560                 result = (buf[o] & 0xff) |
561                         ((buf[o+1] & 0xff) << 8) |
562                         ((buf[o+2] & 0xff) << 16) |
563                         ((buf[o+3] & 0xffL) << 24) |
564                         ((buf[o+4] & 0xffL) << 32) |
565                         ((buf[o+5] & 0xffL) << 40) |
566                         ((long)(buf[o+6]) << 48);
567                 break;
568             case 6:
569                 result = (buf[o] & 0xff) |
570                         ((buf[o+1] & 0xff) << 8) |
571                         ((buf[o+2] & 0xff) << 16) |
572                         ((buf[o+3] & 0xffL) << 24) |
573                         ((buf[o+4] & 0xffL) << 32) |
574                         ((long)(buf[o+5]) << 40);
575                 break;
576             case 5:
577                 result = (buf[o] & 0xff) |
578                         ((buf[o+1] & 0xff) << 8) |
579                         ((buf[o+2] & 0xff) << 16) |
580                         ((buf[o+3] & 0xffL) << 24) |
581                         ((long)(buf[o+4]) << 32);
582                 break;
583             case 4:
584                 result = (buf[o] & 0xff) |
585                         ((buf[o+1] & 0xff) << 8) |
586                         ((buf[o+2] & 0xff) << 16) |
587                         (((long)buf[o+3]) << 24);
588                 break;
589             case 3:
590                 result = (buf[o] & 0xff) |
591                         ((buf[o+1] & 0xff) << 8) |
592                         (buf[o+2] << 16);
593                 break;
594             case 2:
595                 result = (buf[o] & 0xff) |
596                         (buf[o+1] << 8);
597                 break;
598             case 1:
599                 result = buf[o];
600                 break;
601             default:
602                 throw new ExceptionWithContext("Invalid size %d for sized long at offset 0x%x", bytes, offset);
603         }
604 
605         offset = o + bytes - dexBuf.baseOffset;
606         return result;
607     }
608 
readString(int utf16Length)609     public String readString(int utf16Length) {
610         int[] ret = new int[1];
611         String value = Utf8Utils.utf8BytesWithUtf16LengthToString(
612                 dexBuf.buf, dexBuf.baseOffset + offset, utf16Length, ret);
613         offset += ret[0];
614         return value;
615     }
616 
peekStringLength(int utf16Length)617     public int peekStringLength(int utf16Length) {
618         int[] ret = new int[1];
619         Utf8Utils.utf8BytesWithUtf16LengthToString(
620             dexBuf.buf, dexBuf.baseOffset + offset, utf16Length, ret);
621         return ret[0];
622     }
623 }
624