Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

array parsing in resources #1994

Closed
azt59 opened this issue Jan 18, 2019 · 8 comments · Fixed by #2000
Closed

array parsing in resources #1994

azt59 opened this issue Jan 18, 2019 · 8 comments · Fixed by #2000
Labels

Comments

@azt59
Copy link

azt59 commented Jan 18, 2019

Information

apktool version 2.4.0-29355f-SNAPSHOT

Error with parsing resources.

I am use this apk

after decode in file res/values/arrays.xml contains the following code

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="autoteka_benefits" />
    <style name="loader_circle_colors" />
    <style name="loader_circle_sizes" />
    <style name="messenger_attachment_options" />
    <style name="messenger_attachment_options_legacy" />
    <style name="on_day_of_week" />
    <style name="pull_refresh_color_scheme" />
    <style name="rating_score_text" />
</resources>

public.xml code

<public type="array" name="autoteka_benefits" id="0x7f030000" />
    <public type="array" name="loader_circle_colors" id="0x7f030001" />
    <public type="array" name="loader_circle_sizes" id="0x7f030002" />
    <public type="array" name="messenger_attachment_options" id="0x7f030003" />
    <public type="array" name="messenger_attachment_options_legacy" id="0x7f030004" />
    <public type="array" name="on_day_of_week" id="0x7f030005" />
    <public type="array" name="pull_refresh_color_scheme" id="0x7f030006" />
    <public type="array" name="rating_score_text" id="0x7f030007" />

im try to list files of this apk via aapt.exe and fount this:

type 2 configCount=1 entryCount=8
      spec resource 0x7f030000 com.avito.android:array/autoteka_benefits: flags=0x00000000
      spec resource 0x7f030001 com.avito.android:array/loader_circle_colors: flags=0x00000000
      spec resource 0x7f030002 com.avito.android:array/loader_circle_sizes: flags=0x00000000
      spec resource 0x7f030003 com.avito.android:array/messenger_attachment_options: flags=0x00000000
      spec resource 0x7f030004 com.avito.android:array/messenger_attachment_options_legacy: flags=0x00000000
      spec resource 0x7f030005 com.avito.android:array/on_day_of_week: flags=0x00000000
      spec resource 0x7f030006 com.avito.android:array/pull_refresh_color_scheme: flags=0x00000000
      spec resource 0x7f030007 com.avito.android:array/rating_score_text: flags=0x00000000
      config (default):
        resource 0x7f030000 com.avito.android:array/autoteka_benefits: <bag>
        resource 0x7f030001 com.avito.android:array/loader_circle_colors: <bag>
        resource 0x7f030002 com.avito.android:array/loader_circle_sizes: <bag>
        resource 0x7f030003 com.avito.android:array/messenger_attachment_options: <bag>
        resource 0x7f030004 com.avito.android:array/messenger_attachment_options_legacy: <bag>
        resource 0x7f030005 com.avito.android:array/on_day_of_week: <bag>
        resource 0x7f030006 com.avito.android:array/pull_refresh_color_scheme: <bag>
        resource 0x7f030007 com.avito.android:array/rating_score_text: <bag>

And aapt2.exe(Android Asset Packaging Tool (aapt) 2:19) print this

type array id=03 entryCount=8
    resource 0x7f030000 array/autoteka_benefits
      () (array) size=10
        ["История регистраций в ГИБДД", "Нахождение в розыске", "Нахождение в залоге", "Наличие ограничений на регистрацию", 
         "Участие в ДТП", "Использование в такси", "Записи о пробеге", "Факты расчёта стоимости страхового ремонта", 
         "История обслуживания у дилеров", "История размещения на Авито"]
    resource 0x7f030001 array/loader_circle_colors
      () (array) size=4
        [@color/blue, @color/red, @color/green, @color/purple]
    resource 0x7f030002 array/loader_circle_sizes
      () (array) size=4
        [44, 34, 54, 25]
    resource 0x7f030003 array/messenger_attachment_options
      () (array) size=3
        ["Отправить фото", "Отправить объявление", "Указать место встречи"]
    resource 0x7f030004 array/messenger_attachment_options_legacy
      () (array) size=2
        ["Отправить фото", "Отправить объявление"]
    resource 0x7f030005 array/on_day_of_week
      () (array) size=7
        ["в воскресенье", "в понедельник", "во вторник", "в среду", 
         "в четверг", "в пятницу", "в субботу"]
    resource 0x7f030006 array/pull_refresh_color_scheme
      () (array) size=4
        [@color/blue, @color/purple, @color/green, @color/red]
    resource 0x7f030007 array/rating_score_text
      () (array) size=6
        ["Нажмите, чтобы оценить", "Нельзя иметь дело", "Не рекомендую", "Есть над чем работать", 
         "Почти нет вопросов", "Всё отлично"]

Your program does not correctly identify the array and its contents.

@Ibuprophen
Copy link

Can you please give me a quick link to the location where the Snapshot builds can be obtained from @azt59?

I had recently lost the link and had just remembered about asking around for it again.

Thanks a bunch! :-)

~Ibuprophen

@azt59
Copy link
Author

azt59 commented Jan 19, 2019

I build it by this instructions https://ibotpeaches.github.io/Apktool/build/

@axtlotic
Copy link

This case is present too in 2.3.4 version, arrays is parsed as styles tags

@iBotPeaches
Copy link
Owner

Confirmed.

@vbarthel-fr
Copy link
Contributor

Hi! I have just ran into the same issue, I spent some times trying to implement a fix and found this solution:

diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTypeSpec.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTypeSpec.java
index 0c2de96d..df07f7c8 100644
--- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTypeSpec.java
+++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTypeSpec.java
@@ -24,6 +24,11 @@ import java.util.*;
  * @author Ryszard Wiśniewski <[email protected]>
  */
 public final class ResTypeSpec {
+
+    public static final String RES_TYPE_NAME_ARRAY = "array";
+    public static final String RES_TYPE_NAME_PLURALS = "plurals";
+    public static final String RES_TYPE_NAME_STYLES = "style";
+
     private final String mName;
     private final Map<String, ResResSpec> mResSpecs = new LinkedHashMap<String, ResResSpec>();
 
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 ee21befd..fae59dbc 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
@@ -19,6 +19,7 @@ package brut.androlib.res.data.value;
 import android.util.TypedValue;
 import brut.androlib.AndrolibException;
 import brut.androlib.res.data.ResPackage;
+import brut.androlib.res.data.ResTypeSpec;
 import brut.util.Duo;
 
 /**
@@ -83,7 +84,7 @@ public class ResValueFactory {
         return new ResStringValue(value, rawValue);
     }
 
-    public ResBagValue bagFactory(int parent, Duo<Integer, ResScalarValue>[] items) throws AndrolibException {
+    public ResBagValue bagFactory(int parent, Duo<Integer, ResScalarValue>[] items, ResTypeSpec resTypeSpec) throws AndrolibException {
         ResReferenceValue parentVal = newReference(parent, null);
 
         if (items.length == 0) {
@@ -93,14 +94,25 @@ public class ResValueFactory {
         if (key == ResAttr.BAG_KEY_ATTR_TYPE) {
             return ResAttr.factory(parentVal, items, this, mPackage);
         }
-        // Android O Preview added an unknown enum for ResTable_map. This is hardcoded as 0 for now.
-        if (key == ResArrayValue.BAG_KEY_ARRAY_START || key == 0) {
+
+        String resTypeName = resTypeSpec.getName();
+
+        // Android O Preview added an unknown enum for c. This is hardcoded as 0 for now.
+        if (ResTypeSpec.RES_TYPE_NAME_ARRAY.equals(resTypeName)
+                || key == ResArrayValue.BAG_KEY_ARRAY_START || key == 0) {
             return new ResArrayValue(parentVal, items);
         }
-        if (key >= ResPluralsValue.BAG_KEY_PLURALS_START && key <= ResPluralsValue.BAG_KEY_PLURALS_END) {
+
+        if (ResTypeSpec.RES_TYPE_NAME_PLURALS.equals(resTypeName) ||
+                (key >= ResPluralsValue.BAG_KEY_PLURALS_START && key <= ResPluralsValue.BAG_KEY_PLURALS_END)) {
             return new ResPluralsValue(parentVal, items);
         }
-        return new ResStyleValue(parentVal, items, this);
+
+        if (ResTypeSpec.RES_TYPE_NAME_STYLES.equals(resTypeName)) {
+            return new ResStyleValue(parentVal, items, this);
+        }
+
+        throw new AndrolibException("unsupported res type name for bags. Found: " + resTypeName);
     }
 
     public ResReferenceValue newReference(int resID, String rawValue) {
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 290a6615..86efecff 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
@@ -347,7 +347,7 @@ public class ARSCDecoder {
             }
         }
 
-        return factory.bagFactory(parent, items);
+        return factory.bagFactory(parent, items, mTypeSpec);
     }
 
     private ResIntBasedValue readValue() throws IOException, AndrolibException {

Instead of using the id of the first item within the bag, I use the name of the res type spec to choose the res bag value to create. The "names" have been found from the aapt2 source code:

https://github.com/aosp-mirror/platform_frameworks_base/blob/e80b45506501815061b079dcb10bf87443bd385d/tools/aapt2/Resources.proto#L84-L94

https://github.com/aosp-mirror/platform_frameworks_base/blob/e80b45506501815061b079dcb10bf87443bd385d/tools/aapt2/Resource.cpp#L105-L132

I kept the previous checks, but we might remove them and use only the check on the names.

Please, feel free to tell me what you think of the solution :) I might submit an MR in the coming days if it's OK for you!

@iBotPeaches
Copy link
Owner

@vbarthel-fr That sounds excellent! Thanks for digging into that. I always knew trusting the first value inside the bag was a bad idea. Your solution looks good. Feel free to put it up for review

@vbarthel-fr
Copy link
Contributor

vbarthel-fr commented Jan 29, 2019

@iBotPeaches Thanks :) Before I submit a pull request, have you any preferences regarding keeping the previous checks? I might not have enough hindsight and experience with the arsc format to fully understand the consequences of those changes!

@vbarthel-fr
Copy link
Contributor

Here is my first attempt: #2000 :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants