289DexFile* dexFileParse(const u1* data, size_t length, int flags)
290{
291 DexFile* pDexFile = NULL;
292 const DexHeader* pHeader;
293 const u1* magic;
294 int result = -1;
295
296 if (length < sizeof(DexHeader)) {
297 ALOGE("too short to be a valid .dex");
298 goto bail;
299 }
300
301 pDexFile = (DexFile*) malloc(sizeof(DexFile));
302 if (pDexFile == NULL)
303 goto bail;
304 memset(pDexFile, 0, sizeof(DexFile));
305
306
309 if (memcmp(data, DEX_OPT_MAGIC, 4) == 0) {
310 magic = data;
311 if (memcmp(magic+4, DEX_OPT_MAGIC_VERS, 4) != 0) {
312 ALOGE("bad opt version (0x%02x %02x %02x %02x)",
313 magic[4], magic[5], magic[6], magic[7]);
314 goto bail;
315 }
316
317 pDexFile->pOptHeader = (const DexOptHeader*) data;
318 ALOGV("Good opt header, DEX offset is %d, flags=0x%02x",
319 pDexFile->pOptHeader->dexOffset, pDexFile->pOptHeader->flags);
320
321
322 if (!dexParseOptData(data, length, pDexFile))
323 goto bail;
324
325
326 data += pDexFile->pOptHeader->dexOffset;
327 length -= pDexFile->pOptHeader->dexOffset;
328 if (pDexFile->pOptHeader->dexLength > length) {
329 ALOGE("File truncated? stored len=%d, rem len=%d",
330 pDexFile->pOptHeader->dexLength, (int) length);
331 goto bail;
332 }
333 length = pDexFile->pOptHeader->dexLength;
334 }
335
336 dexFileSetupBasicPointers(pDexFile, data);
337 pHeader = pDexFile->pHeader;
338
339 if (!dexHasValidMagic(pHeader)) {
340 goto bail;
341 }
342
343
348 if (flags & kDexParseVerifyChecksum) {
349 u4 adler = dexComputeChecksum(pHeader);
350 if (adler != pHeader->checksum) {
351 ALOGE("ERROR: bad checksum (%08x vs %08x)",
352 adler, pHeader->checksum);
353 if (!(flags & kDexParseContinueOnError))
354 goto bail;
355 } else {
356 ALOGV("+++ adler32 checksum (%08x) verified", adler);
357 }
358
359 const DexOptHeader* pOptHeader = pDexFile->pOptHeader;
360 if (pOptHeader != NULL) {
361 adler = dexComputeOptChecksum(pOptHeader);
362 if (adler != pOptHeader->checksum) {
363 ALOGE("ERROR: bad opt checksum (%08x vs %08x)",
364 adler, pOptHeader->checksum);
365 if (!(flags & kDexParseContinueOnError))
366 goto bail;
367 } else {
368 ALOGV("+++ adler32 opt checksum (%08x) verified", adler);
369 }
370 }
371 }
372
373
379 if (kVerifySignature) {
380 unsigned char sha1Digest[kSHA1DigestLen];
381 const int nonSum = sizeof(pHeader->magic) + sizeof(pHeader->checksum) +
382 kSHA1DigestLen;
383
384 dexComputeSHA1Digest(data + nonSum, length - nonSum, sha1Digest);
385 if (memcmp(sha1Digest, pHeader->signature, kSHA1DigestLen) != 0) {
386 char tmpBuf1[kSHA1DigestOutputLen];
387 char tmpBuf2[kSHA1DigestOutputLen];
388 ALOGE("ERROR: bad SHA1 digest (%s vs %s)",
389 dexSHA1DigestToStr(sha1Digest, tmpBuf1),
390 dexSHA1DigestToStr(pHeader->signature, tmpBuf2));
391 if (!(flags & kDexParseContinueOnError))
392 goto bail;
393 } else {
394 ALOGV("+++ sha1 digest verified");
395 }
396 }
397
398 if (pHeader->fileSize != length) {
399 ALOGE("ERROR: stored file size (%d) != expected (%d)",
400 (int) pHeader->fileSize, (int) length);
401 if (!(flags & kDexParseContinueOnError))
402 goto bail;
403 }
404
405 if (pHeader->classDefsSize == 0) {
406 ALOGE("ERROR: DEX file has no classes in it, failing");
407 goto bail;
408 }
409
410
413 result = 0;
414
415bail:
416 if (result != 0 && pDexFile != NULL) {
417 dexFileFree(pDexFile);
418 pDexFile = NULL;
419 }
420 return pDexFile;
421}