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