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