diff options
author | Ryan Mitchell <rtmitchell@google.com> | 2018-03-29 15:49:10 -0700 |
---|---|---|
committer | Ryan Mitchell <rtmitchell@google.com> | 2018-04-02 12:20:14 -0700 |
commit | ea9e8b447a5d24d1b199507dac203c69d81736e2 (patch) | |
tree | 5c602f75762e20d91aaed16f110b9383a8b35b6e /libs/androidfw/tests/ResTable_test.cpp | |
parent | ecc58adba14232f5580720035ffb48bb4ddee1ba (diff) |
Added decoding of truncated AAPT string lengths.
AAPT incorrectly writes a truncated string length when the string size
exceeded the maximum possible encode length value (0x7FFF). To decode a
truncated length, this change iterates through length values that end
in the encode length bits. Strings that exceed the maximum encode length
are not placed into StringPools in AAPT2.
Test: Successfully ran broken apps from the duplicates of the bugs
provided and created tests
Bug: 69320870
Change-Id: I99dd9b63e91ac250f81d5dfc26b7c0e6276ae162
Diffstat (limited to 'libs/androidfw/tests/ResTable_test.cpp')
-rw-r--r-- | libs/androidfw/tests/ResTable_test.cpp | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/libs/androidfw/tests/ResTable_test.cpp b/libs/androidfw/tests/ResTable_test.cpp index 2df41305237e..326474e16e5d 100644 --- a/libs/androidfw/tests/ResTable_test.cpp +++ b/libs/androidfw/tests/ResTable_test.cpp @@ -424,4 +424,56 @@ TEST(ResTableTest, GetConfigurationsReturnsUniqueList) { EXPECT_EQ(1, std::count(locales.begin(), locales.end(), String8("sv"))); } +TEST(ResTableTest, TruncatedEncodeLength) { + std::string contents; + ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/length_decode/length_decode_valid.apk", + "resources.arsc", &contents)); + + ResTable table; + ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size())); + + Res_value val; + ssize_t block = table.getResource(0x7f010001, &val, MAY_NOT_BE_BAG); + ASSERT_GE(block, 0); + ASSERT_EQ(Res_value::TYPE_STRING, val.dataType); + + const ResStringPool* pool = table.getTableStringBlock(block); + ASSERT_TRUE(pool != NULL); + ASSERT_LT(val.data, pool->size()); + + // Make sure a string with a truncated length is read to its correct length + size_t str_len; + const char* target_str8 = pool->string8At(val.data, &str_len); + ASSERT_TRUE(target_str8 != NULL); + ASSERT_EQ(size_t(40076), String8(target_str8, str_len).size()); + ASSERT_EQ(target_str8[40075], ']'); + + const char16_t* target_str16 = pool->stringAt(val.data, &str_len); + ASSERT_TRUE(target_str16 != NULL); + ASSERT_EQ(size_t(40076), String16(target_str16, str_len).size()); + ASSERT_EQ(target_str8[40075], (char16_t) ']'); + + // Load an edited apk with the null terminator removed from the end of the + // string + std::string invalid_contents; + ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/length_decode/length_decode_invalid.apk", + "resources.arsc", &invalid_contents)); + ResTable invalid_table; + ASSERT_EQ(NO_ERROR, invalid_table.add(invalid_contents.data(), invalid_contents.size())); + + Res_value invalid_val; + ssize_t invalid_block = invalid_table.getResource(0x7f010001, &invalid_val, MAY_NOT_BE_BAG); + ASSERT_GE(invalid_block, 0); + ASSERT_EQ(Res_value::TYPE_STRING, invalid_val.dataType); + + const ResStringPool* invalid_pool = invalid_table.getTableStringBlock(invalid_block); + ASSERT_TRUE(invalid_pool != NULL); + ASSERT_LT(invalid_val.data, invalid_pool->size()); + + // Make sure a string with a truncated length that is not null terminated errors + // and does not return the string + ASSERT_TRUE(invalid_pool->string8At(invalid_val.data, &str_len) == NULL); + ASSERT_TRUE(invalid_pool->stringAt(invalid_val.data, &str_len) == NULL); +} + } // namespace android |