|
49 | 49 | import java.util.zip.ZipEntry;
|
50 | 50 | import java.util.zip.ZipFile;
|
51 | 51 |
|
52 |
| -import org.xmlpull.v1.XmlPullParser; |
| 52 | +import org.apache.commons.io.IOUtils; |
53 | 53 |
|
54 |
| -import android.content.res.AXmlResourceParser; |
| 54 | +import pxb.android.axml.AxmlReader; |
| 55 | +import pxb.android.axml.AxmlVisitor; |
| 56 | +import pxb.android.axml.NodeVisitor; |
55 | 57 | import soot.dexpler.DalvikThrowAnalysis;
|
56 | 58 | import soot.jimple.spark.internal.ClientAccessibilityOracle;
|
57 | 59 | import soot.jimple.spark.internal.PublicAndProtectedAccessibility;
|
|
72 | 74 | import soot.util.MapNumberer;
|
73 | 75 | import soot.util.Numberer;
|
74 | 76 | import soot.util.StringNumberer;
|
75 |
| -import test.AXMLPrinter; |
76 | 77 |
|
77 | 78 | /** Manages the SootClasses of the application being analyzed. */
|
78 | 79 | public class Scene // extends AbstractHost
|
@@ -395,6 +396,14 @@ else if (apk != null)
|
395 | 396 | return androidAPIVersion;
|
396 | 397 | }
|
397 | 398 |
|
| 399 | + private static class AndroidVersionInfo { |
| 400 | + |
| 401 | + public int sdkTargetVersion = -1; |
| 402 | + public int minSdkVersion = -1; |
| 403 | + public int platformBuildVersionCode = -1; |
| 404 | + |
| 405 | + } |
| 406 | + |
398 | 407 | private int getTargetSDKVersion(String apkFile, String platformJARs) {
|
399 | 408 | // get AndroidManifest
|
400 | 409 | InputStream manifestIS = null;
|
@@ -423,75 +432,63 @@ private int getTargetSDKVersion(String apkFile, String platformJARs) {
|
423 | 432 |
|
424 | 433 | // process AndroidManifest.xml
|
425 | 434 | int maxAPI = getMaxAPIAvailable(platformJARs);
|
426 |
| - int sdkTargetVersion = -1; |
427 |
| - int minSdkVersion = -1; |
428 |
| - int platformBuildVersionCode = -1; |
| 435 | + final AndroidVersionInfo versionInfo = new AndroidVersionInfo(); |
429 | 436 | try {
|
430 |
| - AXmlResourceParser parser = new AXmlResourceParser(); |
431 |
| - parser.open(manifestIS); |
432 |
| - int depth = 0; |
433 |
| - loop: while (true) { |
434 |
| - int type = parser.next(); |
435 |
| - switch (type) { |
436 |
| - case XmlPullParser.START_DOCUMENT: { |
437 |
| - break; |
438 |
| - } |
439 |
| - case XmlPullParser.END_DOCUMENT: |
440 |
| - break loop; |
441 |
| - case XmlPullParser.START_TAG: { |
442 |
| - depth++; |
443 |
| - String tagName = parser.getName(); |
444 |
| - if (depth == 1 && tagName.equals("manifest")) { |
445 |
| - for (int i = 0; i != parser.getAttributeCount(); ++i) { |
446 |
| - String attributeName = parser.getAttributeName(i); |
447 |
| - String attributeValue = AXMLPrinter.getAttributeValue(parser, i); |
448 |
| - if (attributeName.equals("platformBuildVersionCode")) { |
449 |
| - platformBuildVersionCode = Integer.parseInt(attributeValue); |
450 |
| - } |
451 |
| - } |
452 |
| - } else if (depth == 2 && tagName.equals("uses-sdk")) { |
453 |
| - for (int i = 0; i != parser.getAttributeCount(); ++i) { |
454 |
| - String attributeName = parser.getAttributeName(i); |
455 |
| - String attributeValue = AXMLPrinter.getAttributeValue(parser, i); |
456 |
| - if (attributeName.equals("targetSdkVersion")) { |
457 |
| - sdkTargetVersion = Integer.parseInt(attributeValue); |
458 |
| - } else if (attributeName.equals("minSdkVersion")) { |
459 |
| - minSdkVersion = Integer.parseInt(attributeValue); |
460 |
| - } |
| 437 | + AxmlReader xmlReader = new AxmlReader(IOUtils.toByteArray(manifestIS)); |
| 438 | + xmlReader.accept(new AxmlVisitor() { |
| 439 | + |
| 440 | + private String nodeName = null; |
| 441 | + |
| 442 | + @Override |
| 443 | + public void attr(String ns, String name, int resourceId, int type, Object obj) { |
| 444 | + super.attr(ns, name, resourceId, type, obj); |
| 445 | + |
| 446 | + if (nodeName != null && name != null) { |
| 447 | + if (nodeName.equals("manifest")) { |
| 448 | + if (name.equals("platformBuildVersionCode")) |
| 449 | + versionInfo.platformBuildVersionCode = Integer.valueOf("" + obj); |
| 450 | + } else if (nodeName.equals("uses-sdk")) { |
| 451 | + if (name.equals("targetSdkVersion")) |
| 452 | + versionInfo.sdkTargetVersion = Integer.valueOf("" + obj); |
| 453 | + else if (name.equals("minSdkVersion")) |
| 454 | + versionInfo.minSdkVersion = Integer.valueOf("" + obj); |
461 | 455 | }
|
462 | 456 | }
|
463 |
| - break; |
464 | 457 | }
|
465 |
| - case XmlPullParser.END_TAG: |
466 |
| - depth--; |
467 |
| - break; |
468 |
| - case XmlPullParser.TEXT: |
469 |
| - break; |
| 458 | + |
| 459 | + @Override |
| 460 | + public NodeVisitor child(String ns, String name) { |
| 461 | + nodeName = name; |
| 462 | + |
| 463 | + return this; |
470 | 464 | }
|
471 |
| - } |
| 465 | + |
| 466 | + }); |
472 | 467 | } catch (Exception e) {
|
473 | 468 | e.printStackTrace();
|
474 | 469 | }
|
475 | 470 |
|
476 | 471 | int APIVersion = -1;
|
477 |
| - if (sdkTargetVersion != -1) { |
478 |
| - if (sdkTargetVersion > maxAPI && minSdkVersion != -1 && minSdkVersion <= maxAPI) { |
479 |
| - G.v().out.println("warning: Android API version '" + sdkTargetVersion |
480 |
| - + "' not available, using minApkVersion '" + minSdkVersion + "' instead"); |
481 |
| - APIVersion = minSdkVersion; |
| 472 | + if (versionInfo.sdkTargetVersion != -1) { |
| 473 | + if (versionInfo.sdkTargetVersion > maxAPI && versionInfo.minSdkVersion != -1 |
| 474 | + && versionInfo.minSdkVersion <= maxAPI) { |
| 475 | + G.v().out.println("warning: Android API version '" + versionInfo.sdkTargetVersion |
| 476 | + + "' not available, using minApkVersion '" + versionInfo.minSdkVersion + "' instead"); |
| 477 | + APIVersion = versionInfo.minSdkVersion; |
482 | 478 | } else {
|
483 |
| - APIVersion = sdkTargetVersion; |
| 479 | + APIVersion = versionInfo.sdkTargetVersion; |
484 | 480 | }
|
485 |
| - } else if (platformBuildVersionCode != -1) { |
486 |
| - if (platformBuildVersionCode > maxAPI && minSdkVersion != -1 && minSdkVersion <= maxAPI) { |
487 |
| - G.v().out.println("warning: Android API version '" + platformBuildVersionCode |
488 |
| - + "' not available, using minApkVersion '" + minSdkVersion + "' instead"); |
489 |
| - APIVersion = minSdkVersion; |
| 481 | + } else if (versionInfo.platformBuildVersionCode != -1) { |
| 482 | + if (versionInfo.platformBuildVersionCode > maxAPI && versionInfo.minSdkVersion != -1 |
| 483 | + && versionInfo.minSdkVersion <= maxAPI) { |
| 484 | + G.v().out.println("warning: Android API version '" + versionInfo.platformBuildVersionCode |
| 485 | + + "' not available, using minApkVersion '" + versionInfo.minSdkVersion + "' instead"); |
| 486 | + APIVersion = versionInfo.minSdkVersion; |
490 | 487 | } else {
|
491 |
| - APIVersion = platformBuildVersionCode; |
| 488 | + APIVersion = versionInfo.platformBuildVersionCode; |
492 | 489 | }
|
493 |
| - } else if (minSdkVersion != -1) { |
494 |
| - APIVersion = minSdkVersion; |
| 490 | + } else if (versionInfo.minSdkVersion != -1) { |
| 491 | + APIVersion = versionInfo.minSdkVersion; |
495 | 492 | } else {
|
496 | 493 | G.v().out
|
497 | 494 | .println("Could not find sdk version in Android manifest! Using default: " + defaultSdkVersion);
|
@@ -928,7 +925,7 @@ public RefType getRefType(String className) {
|
928 | 925 | * with the given name can be found.
|
929 | 926 | */
|
930 | 927 | public RefType getRefTypeUnsafe(String className) {
|
931 |
| - RefType refType = nameToClass.get(className); |
| 928 | + RefType refType = nameToClass.get(className); |
932 | 929 | return refType;
|
933 | 930 | }
|
934 | 931 |
|
@@ -961,9 +958,8 @@ public SootClass getSootClassUnsafe(String className) {
|
961 | 958 | if (tsc != null)
|
962 | 959 | return tsc;
|
963 | 960 | }
|
964 |
| - |
965 |
| - if (allowsPhantomRefs() || |
966 |
| - className.equals(SootClass.INVOKEDYNAMIC_DUMMY_CLASS_NAME)) { |
| 961 | + |
| 962 | + if (allowsPhantomRefs() || className.equals(SootClass.INVOKEDYNAMIC_DUMMY_CLASS_NAME)) { |
967 | 963 | SootClass c = new SootClass(className);
|
968 | 964 | c.isPhantom = true;
|
969 | 965 | addClassSilent(c);
|
|
0 commit comments