From 8254764c6c10b42f2db7d408ae32de7d7bdf082a Mon Sep 17 00:00:00 2001 From: Connor Tumbleson Date: Thu, 14 May 2015 13:22:43 -0500 Subject: [PATCH] More robust ResFileValue detection Previously in 4882396163f978884256e008fc7fae9201f156b4, strings that resembled a filepath (ie res/foo/file), would be assigned to a ResFileValue, which when attempted to be casted to ResScalarValue would error out. Attempting to check the filesystem for such files, slowed apktool's execution majorly. In order to prevent this, the ClassCastException and other checks related to checking ResFileValue when type is string was added. This allows bogus strings such as (res/foo/file) to be added, but the exception is caught and allows decoding to continues. Fixes #921. --- .../java/brut/androlib/res/data/ResType.java | 4 ++++ .../androlib/res/data/value/ResFileValue.java | 5 +++++ .../androlib/res/data/value/ResValueFactory.java | 2 +- .../brut/androlib/res/decoder/ARSCDecoder.java | 16 +++++++++++++++- .../brut/apktool/testapp/res/raw/no_extension | 1 + 5 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 brut.apktool/apktool-lib/src/test/resources/brut/apktool/testapp/res/raw/no_extension diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResType.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResType.java index d4640421..1d22b848 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResType.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResType.java @@ -40,6 +40,10 @@ public final class ResType { return mName; } + public boolean isString() { + return mName.equalsIgnoreCase("string"); + } + public Set listResSpecs() { return new LinkedHashSet(mResSpecs.values()); } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResFileValue.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResFileValue.java index 623709da..56f95643 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResFileValue.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResFileValue.java @@ -39,4 +39,9 @@ public class ResFileValue extends ResValue { } return mPath.substring(4); } + + @Override + public String toString() { + return mPath; + } } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResValueFactory.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResValueFactory.java index 6d611c06..c0c5177e 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResValueFactory.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResValueFactory.java @@ -67,7 +67,7 @@ public class ResValueFactory { } public ResValue factory(String value) { - if (value.startsWith("res/") && value.contains(".")) { + if (value.startsWith("res/")) { return new ResFileValue(value); } return new ResStringValue(value); diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java index 35e6cf49..6ed58cfd 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java @@ -202,6 +202,9 @@ public class ARSCDecoder { ResValue value = (flags & ENTRY_FLAG_COMPLEX) == 0 ? readValue() : readComplexEntry(); + if (mType.isString() && value instanceof ResFileValue) { + value = new ResStringValue(value.toString()); + } if (mConfig == null) { return; } @@ -229,8 +232,19 @@ public class ARSCDecoder { ResValueFactory factory = mPkg.getValueFactory(); Duo[] items = new Duo[count]; + ResValue resValue; + int resId; + for (int i = 0; i < count; i++) { - items[i] = new Duo(mIn.readInt(), (ResScalarValue) readValue()); + resId = mIn.readInt(); + resValue = readValue(); + + try { + items[i] = new Duo(resId, (ResScalarValue) resValue); + } catch (ClassCastException ex) { + resValue = new ResStringValue(resValue.toString()); + items[i] = new Duo(resId, (ResScalarValue) resValue); + } } return factory.bagFactory(parent, items); diff --git a/brut.apktool/apktool-lib/src/test/resources/brut/apktool/testapp/res/raw/no_extension b/brut.apktool/apktool-lib/src/test/resources/brut/apktool/testapp/res/raw/no_extension new file mode 100644 index 00000000..be0f9bb5 --- /dev/null +++ b/brut.apktool/apktool-lib/src/test/resources/brut/apktool/testapp/res/raw/no_extension @@ -0,0 +1 @@ +This file has no extension. \ No newline at end of file