• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "dex_file.h"
18 
19 #include <memory>
20 
21 #include "base/stl_util.h"
22 #include "base/unix_file/fd_file.h"
23 #include "common_runtime_test.h"
24 #include "dex_file-inl.h"
25 #include "os.h"
26 #include "scoped_thread_state_change.h"
27 #include "thread-inl.h"
28 
29 namespace art {
30 
31 class DexFileTest : public CommonRuntimeTest {};
32 
TEST_F(DexFileTest,Open)33 TEST_F(DexFileTest, Open) {
34   ScopedObjectAccess soa(Thread::Current());
35   std::unique_ptr<const DexFile> dex(OpenTestDexFile("Nested"));
36   ASSERT_TRUE(dex.get() != nullptr);
37 }
38 
39 static const uint8_t kBase64Map[256] = {
40   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
41   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
42   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
43   255, 255, 255, 255, 255, 255, 255,  62, 255, 255, 255,  63,
44   52,  53,  54,  55,  56,  57,  58,  59,  60,  61, 255, 255,
45   255, 254, 255, 255, 255,   0,   1,   2,   3,   4,   5,   6,
46     7,   8,   9,  10,  11,  12,  13,  14,  15,  16,  17,  18,  // NOLINT
47    19,  20,  21,  22,  23,  24,  25, 255, 255, 255, 255, 255,  // NOLINT
48   255,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,
49    37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  // NOLINT
50    49,  50,  51, 255, 255, 255, 255, 255, 255, 255, 255, 255,  // NOLINT
51   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
52   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
53   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
54   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
55   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
56   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
57   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
58   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
59   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
60   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
61   255, 255, 255, 255
62 };
63 
DecodeBase64(const char * src,size_t * dst_size)64 static inline uint8_t* DecodeBase64(const char* src, size_t* dst_size) {
65   std::vector<uint8_t> tmp;
66   uint32_t t = 0, y = 0;
67   int g = 3;
68   for (size_t i = 0; src[i] != '\0'; ++i) {
69     uint8_t c = kBase64Map[src[i] & 0xFF];
70     if (c == 255) continue;
71     // the final = symbols are read and used to trim the remaining bytes
72     if (c == 254) {
73       c = 0;
74       // prevent g < 0 which would potentially allow an overflow later
75       if (--g < 0) {
76         *dst_size = 0;
77         return nullptr;
78       }
79     } else if (g != 3) {
80       // we only allow = to be at the end
81       *dst_size = 0;
82       return nullptr;
83     }
84     t = (t << 6) | c;
85     if (++y == 4) {
86       tmp.push_back((t >> 16) & 255);
87       if (g > 1) {
88         tmp.push_back((t >> 8) & 255);
89       }
90       if (g > 2) {
91         tmp.push_back(t & 255);
92       }
93       y = t = 0;
94     }
95   }
96   if (y != 0) {
97     *dst_size = 0;
98     return nullptr;
99   }
100   std::unique_ptr<uint8_t[]> dst(new uint8_t[tmp.size()]);
101   if (dst_size != nullptr) {
102     *dst_size = tmp.size();
103   } else {
104     *dst_size = 0;
105   }
106   std::copy(tmp.begin(), tmp.end(), dst.get());
107   return dst.release();
108 }
109 
110 // Although this is the same content logically as the Nested test dex,
111 // the DexFileHeader test is sensitive to subtle changes in the
112 // contents due to the checksum etc, so we embed the exact input here.
113 //
114 // class Nested {
115 //     class Inner {
116 //     }
117 // }
118 static const char kRawDex[] =
119   "ZGV4CjAzNQAQedgAe7gM1B/WHsWJ6L7lGAISGC7yjD2IAwAAcAAAAHhWNBIAAAAAAAAAAMQCAAAP"
120   "AAAAcAAAAAcAAACsAAAAAgAAAMgAAAABAAAA4AAAAAMAAADoAAAAAgAAAAABAABIAgAAQAEAAK4B"
121   "AAC2AQAAvQEAAM0BAADXAQAA+wEAABsCAAA+AgAAUgIAAF8CAABiAgAAZgIAAHMCAAB5AgAAgQIA"
122   "AAIAAAADAAAABAAAAAUAAAAGAAAABwAAAAkAAAAJAAAABgAAAAAAAAAKAAAABgAAAKgBAAAAAAEA"
123   "DQAAAAAAAQAAAAAAAQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAIAAAAiAEAAKsCAAAA"
124   "AAAAAQAAAAAAAAAFAAAAAAAAAAgAAACYAQAAuAIAAAAAAAACAAAAlAIAAJoCAAABAAAAowIAAAIA"
125   "AgABAAAAiAIAAAYAAABbAQAAcBACAAAADgABAAEAAQAAAI4CAAAEAAAAcBACAAAADgBAAQAAAAAA"
126   "AAAAAAAAAAAATAEAAAAAAAAAAAAAAAAAAAEAAAABAAY8aW5pdD4ABUlubmVyAA5MTmVzdGVkJElu"
127   "bmVyOwAITE5lc3RlZDsAIkxkYWx2aWsvYW5ub3RhdGlvbi9FbmNsb3NpbmdDbGFzczsAHkxkYWx2"
128   "aWsvYW5ub3RhdGlvbi9Jbm5lckNsYXNzOwAhTGRhbHZpay9hbm5vdGF0aW9uL01lbWJlckNsYXNz"
129   "ZXM7ABJMamF2YS9sYW5nL09iamVjdDsAC05lc3RlZC5qYXZhAAFWAAJWTAALYWNjZXNzRmxhZ3MA"
130   "BG5hbWUABnRoaXMkMAAFdmFsdWUAAgEABw4AAQAHDjwAAgIBDhgBAgMCCwQADBcBAgQBDhwBGAAA"
131   "AQEAAJAgAICABNQCAAABAAGAgATwAgAAEAAAAAAAAAABAAAAAAAAAAEAAAAPAAAAcAAAAAIAAAAH"
132   "AAAArAAAAAMAAAACAAAAyAAAAAQAAAABAAAA4AAAAAUAAAADAAAA6AAAAAYAAAACAAAAAAEAAAMQ"
133   "AAACAAAAQAEAAAEgAAACAAAAVAEAAAYgAAACAAAAiAEAAAEQAAABAAAAqAEAAAIgAAAPAAAArgEA"
134   "AAMgAAACAAAAiAIAAAQgAAADAAAAlAIAAAAgAAACAAAAqwIAAAAQAAABAAAAxAIAAA==";
135 
OpenDexFileBase64(const char * base64,const char * location)136 static std::unique_ptr<const DexFile> OpenDexFileBase64(const char* base64,
137                                                         const char* location) {
138   // decode base64
139   CHECK(base64 != nullptr);
140   size_t length;
141   std::unique_ptr<uint8_t[]> dex_bytes(DecodeBase64(base64, &length));
142   CHECK(dex_bytes.get() != nullptr);
143 
144   // write to provided file
145   std::unique_ptr<File> file(OS::CreateEmptyFile(location));
146   CHECK(file.get() != nullptr);
147   if (!file->WriteFully(dex_bytes.get(), length)) {
148     PLOG(FATAL) << "Failed to write base64 as dex file";
149   }
150   if (file->FlushCloseOrErase() != 0) {
151     PLOG(FATAL) << "Could not flush and close test file.";
152   }
153   file.reset();
154 
155   // read dex file
156   ScopedObjectAccess soa(Thread::Current());
157   std::string error_msg;
158   std::vector<std::unique_ptr<const DexFile>> tmp;
159   bool success = DexFile::Open(location, location, &error_msg, &tmp);
160   CHECK(success) << error_msg;
161   EXPECT_EQ(1U, tmp.size());
162   std::unique_ptr<const DexFile> dex_file = std::move(tmp[0]);
163   EXPECT_EQ(PROT_READ, dex_file->GetPermissions());
164   EXPECT_TRUE(dex_file->IsReadOnly());
165   return dex_file;
166 }
167 
TEST_F(DexFileTest,Header)168 TEST_F(DexFileTest, Header) {
169   ScratchFile tmp;
170   std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kRawDex, tmp.GetFilename().c_str()));
171   ASSERT_TRUE(raw.get() != nullptr);
172 
173   const DexFile::Header& header = raw->GetHeader();
174   // TODO: header.magic_
175   EXPECT_EQ(0x00d87910U, header.checksum_);
176   // TODO: header.signature_
177   EXPECT_EQ(904U, header.file_size_);
178   EXPECT_EQ(112U, header.header_size_);
179   EXPECT_EQ(0U, header.link_size_);
180   EXPECT_EQ(0U, header.link_off_);
181   EXPECT_EQ(15U, header.string_ids_size_);
182   EXPECT_EQ(112U, header.string_ids_off_);
183   EXPECT_EQ(7U, header.type_ids_size_);
184   EXPECT_EQ(172U, header.type_ids_off_);
185   EXPECT_EQ(2U, header.proto_ids_size_);
186   EXPECT_EQ(200U, header.proto_ids_off_);
187   EXPECT_EQ(1U, header.field_ids_size_);
188   EXPECT_EQ(224U, header.field_ids_off_);
189   EXPECT_EQ(3U, header.method_ids_size_);
190   EXPECT_EQ(232U, header.method_ids_off_);
191   EXPECT_EQ(2U, header.class_defs_size_);
192   EXPECT_EQ(256U, header.class_defs_off_);
193   EXPECT_EQ(584U, header.data_size_);
194   EXPECT_EQ(320U, header.data_off_);
195 
196   EXPECT_EQ(header.checksum_, raw->GetLocationChecksum());
197 }
198 
TEST_F(DexFileTest,GetLocationChecksum)199 TEST_F(DexFileTest, GetLocationChecksum) {
200   ScopedObjectAccess soa(Thread::Current());
201   std::unique_ptr<const DexFile> raw(OpenTestDexFile("Main"));
202   EXPECT_NE(raw->GetHeader().checksum_, raw->GetLocationChecksum());
203 }
204 
TEST_F(DexFileTest,GetChecksum)205 TEST_F(DexFileTest, GetChecksum) {
206   uint32_t checksum;
207   ScopedObjectAccess soa(Thread::Current());
208   std::string error_msg;
209   EXPECT_TRUE(DexFile::GetChecksum(GetLibCoreDexFileNames()[0].c_str(), &checksum, &error_msg))
210       << error_msg;
211   EXPECT_EQ(java_lang_dex_file_->GetLocationChecksum(), checksum);
212 }
213 
TEST_F(DexFileTest,ClassDefs)214 TEST_F(DexFileTest, ClassDefs) {
215   ScopedObjectAccess soa(Thread::Current());
216   std::unique_ptr<const DexFile> raw(OpenTestDexFile("Nested"));
217   ASSERT_TRUE(raw.get() != nullptr);
218   EXPECT_EQ(2U, raw->NumClassDefs());
219 
220   const DexFile::ClassDef& c0 = raw->GetClassDef(0);
221   EXPECT_STREQ("LNested$Inner;", raw->GetClassDescriptor(c0));
222 
223   const DexFile::ClassDef& c1 = raw->GetClassDef(1);
224   EXPECT_STREQ("LNested;", raw->GetClassDescriptor(c1));
225 }
226 
TEST_F(DexFileTest,GetMethodSignature)227 TEST_F(DexFileTest, GetMethodSignature) {
228   ScopedObjectAccess soa(Thread::Current());
229   std::unique_ptr<const DexFile> raw(OpenTestDexFile("GetMethodSignature"));
230   ASSERT_TRUE(raw.get() != nullptr);
231   EXPECT_EQ(1U, raw->NumClassDefs());
232 
233   const DexFile::ClassDef& class_def = raw->GetClassDef(0);
234   ASSERT_STREQ("LGetMethodSignature;", raw->GetClassDescriptor(class_def));
235 
236   const uint8_t* class_data = raw->GetClassData(class_def);
237   ASSERT_TRUE(class_data != nullptr);
238   ClassDataItemIterator it(*raw, class_data);
239 
240   EXPECT_EQ(1u, it.NumDirectMethods());
241 
242   // Check the signature for the static initializer.
243   {
244     ASSERT_EQ(1U, it.NumDirectMethods());
245     const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex());
246     const char* name = raw->StringDataByIdx(method_id.name_idx_);
247     ASSERT_STREQ("<init>", name);
248     std::string signature(raw->GetMethodSignature(method_id).ToString());
249     ASSERT_EQ("()V", signature);
250   }
251 
252   // Check both virtual methods.
253   ASSERT_EQ(2U, it.NumVirtualMethods());
254   {
255     it.Next();
256     const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex());
257 
258     const char* name = raw->StringDataByIdx(method_id.name_idx_);
259     ASSERT_STREQ("m1", name);
260 
261     std::string signature(raw->GetMethodSignature(method_id).ToString());
262     ASSERT_EQ("(IDJLjava/lang/Object;)Ljava/lang/Float;", signature);
263   }
264 
265   {
266     it.Next();
267     const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex());
268 
269     const char* name = raw->StringDataByIdx(method_id.name_idx_);
270     ASSERT_STREQ("m2", name);
271 
272     std::string signature(raw->GetMethodSignature(method_id).ToString());
273     ASSERT_EQ("(ZSC)LGetMethodSignature;", signature);
274   }
275 }
276 
TEST_F(DexFileTest,FindStringId)277 TEST_F(DexFileTest, FindStringId) {
278   ScopedObjectAccess soa(Thread::Current());
279   std::unique_ptr<const DexFile> raw(OpenTestDexFile("GetMethodSignature"));
280   ASSERT_TRUE(raw.get() != nullptr);
281   EXPECT_EQ(1U, raw->NumClassDefs());
282 
283   const char* strings[] = { "LGetMethodSignature;", "Ljava/lang/Float;", "Ljava/lang/Object;",
284       "D", "I", "J", nullptr };
285   for (size_t i = 0; strings[i] != nullptr; i++) {
286     const char* str = strings[i];
287     const DexFile::StringId* str_id = raw->FindStringId(str);
288     const char* dex_str = raw->GetStringData(*str_id);
289     EXPECT_STREQ(dex_str, str);
290   }
291 }
292 
TEST_F(DexFileTest,FindTypeId)293 TEST_F(DexFileTest, FindTypeId) {
294   for (size_t i = 0; i < java_lang_dex_file_->NumTypeIds(); i++) {
295     const char* type_str = java_lang_dex_file_->StringByTypeIdx(i);
296     const DexFile::StringId* type_str_id = java_lang_dex_file_->FindStringId(type_str);
297     ASSERT_TRUE(type_str_id != nullptr);
298     uint32_t type_str_idx = java_lang_dex_file_->GetIndexForStringId(*type_str_id);
299     const DexFile::TypeId* type_id = java_lang_dex_file_->FindTypeId(type_str_idx);
300     ASSERT_EQ(type_id, java_lang_dex_file_->FindTypeId(type_str));
301     ASSERT_TRUE(type_id != nullptr);
302     EXPECT_EQ(java_lang_dex_file_->GetIndexForTypeId(*type_id), i);
303   }
304 }
305 
TEST_F(DexFileTest,FindProtoId)306 TEST_F(DexFileTest, FindProtoId) {
307   for (size_t i = 0; i < java_lang_dex_file_->NumProtoIds(); i++) {
308     const DexFile::ProtoId& to_find = java_lang_dex_file_->GetProtoId(i);
309     const DexFile::TypeList* to_find_tl = java_lang_dex_file_->GetProtoParameters(to_find);
310     std::vector<uint16_t> to_find_types;
311     if (to_find_tl != nullptr) {
312       for (size_t j = 0; j < to_find_tl->Size(); j++) {
313         to_find_types.push_back(to_find_tl->GetTypeItem(j).type_idx_);
314       }
315     }
316     const DexFile::ProtoId* found =
317         java_lang_dex_file_->FindProtoId(to_find.return_type_idx_, to_find_types);
318     ASSERT_TRUE(found != nullptr);
319     EXPECT_EQ(java_lang_dex_file_->GetIndexForProtoId(*found), i);
320   }
321 }
322 
TEST_F(DexFileTest,FindMethodId)323 TEST_F(DexFileTest, FindMethodId) {
324   for (size_t i = 0; i < java_lang_dex_file_->NumMethodIds(); i++) {
325     const DexFile::MethodId& to_find = java_lang_dex_file_->GetMethodId(i);
326     const DexFile::TypeId& klass = java_lang_dex_file_->GetTypeId(to_find.class_idx_);
327     const DexFile::StringId& name = java_lang_dex_file_->GetStringId(to_find.name_idx_);
328     const DexFile::ProtoId& signature = java_lang_dex_file_->GetProtoId(to_find.proto_idx_);
329     const DexFile::MethodId* found = java_lang_dex_file_->FindMethodId(klass, name, signature);
330     ASSERT_TRUE(found != nullptr) << "Didn't find method " << i << ": "
331         << java_lang_dex_file_->StringByTypeIdx(to_find.class_idx_) << "."
332         << java_lang_dex_file_->GetStringData(name)
333         << java_lang_dex_file_->GetMethodSignature(to_find);
334     EXPECT_EQ(java_lang_dex_file_->GetIndexForMethodId(*found), i);
335   }
336 }
337 
TEST_F(DexFileTest,FindFieldId)338 TEST_F(DexFileTest, FindFieldId) {
339   for (size_t i = 0; i < java_lang_dex_file_->NumFieldIds(); i++) {
340     const DexFile::FieldId& to_find = java_lang_dex_file_->GetFieldId(i);
341     const DexFile::TypeId& klass = java_lang_dex_file_->GetTypeId(to_find.class_idx_);
342     const DexFile::StringId& name = java_lang_dex_file_->GetStringId(to_find.name_idx_);
343     const DexFile::TypeId& type = java_lang_dex_file_->GetTypeId(to_find.type_idx_);
344     const DexFile::FieldId* found = java_lang_dex_file_->FindFieldId(klass, name, type);
345     ASSERT_TRUE(found != nullptr) << "Didn't find field " << i << ": "
346         << java_lang_dex_file_->StringByTypeIdx(to_find.type_idx_) << " "
347         << java_lang_dex_file_->StringByTypeIdx(to_find.class_idx_) << "."
348         << java_lang_dex_file_->GetStringData(name);
349     EXPECT_EQ(java_lang_dex_file_->GetIndexForFieldId(*found), i);
350   }
351 }
352 
TEST_F(DexFileTest,GetMultiDexClassesDexName)353 TEST_F(DexFileTest, GetMultiDexClassesDexName) {
354   ASSERT_EQ("classes.dex", DexFile::GetMultiDexClassesDexName(0));
355   ASSERT_EQ("classes2.dex", DexFile::GetMultiDexClassesDexName(1));
356   ASSERT_EQ("classes3.dex", DexFile::GetMultiDexClassesDexName(2));
357   ASSERT_EQ("classes100.dex", DexFile::GetMultiDexClassesDexName(99));
358 }
359 
TEST_F(DexFileTest,GetMultiDexLocation)360 TEST_F(DexFileTest, GetMultiDexLocation) {
361   std::string dex_location_str = "/system/app/framework.jar";
362   const char* dex_location = dex_location_str.c_str();
363   ASSERT_EQ("/system/app/framework.jar", DexFile::GetMultiDexLocation(0, dex_location));
364   ASSERT_EQ("/system/app/framework.jar:classes2.dex",
365             DexFile::GetMultiDexLocation(1, dex_location));
366   ASSERT_EQ("/system/app/framework.jar:classes101.dex",
367             DexFile::GetMultiDexLocation(100, dex_location));
368 }
369 
TEST_F(DexFileTest,GetDexCanonicalLocation)370 TEST_F(DexFileTest, GetDexCanonicalLocation) {
371   ScratchFile file;
372   UniqueCPtr<const char[]> dex_location_real(realpath(file.GetFilename().c_str(), nullptr));
373   std::string dex_location(dex_location_real.get());
374 
375   ASSERT_EQ(dex_location, DexFile::GetDexCanonicalLocation(dex_location.c_str()));
376   std::string multidex_location = DexFile::GetMultiDexLocation(1, dex_location.c_str());
377   ASSERT_EQ(multidex_location, DexFile::GetDexCanonicalLocation(multidex_location.c_str()));
378 
379   std::string dex_location_sym = dex_location + "symlink";
380   ASSERT_EQ(0, symlink(dex_location.c_str(), dex_location_sym.c_str()));
381 
382   ASSERT_EQ(dex_location, DexFile::GetDexCanonicalLocation(dex_location_sym.c_str()));
383 
384   std::string multidex_location_sym = DexFile::GetMultiDexLocation(1, dex_location_sym.c_str());
385   ASSERT_EQ(multidex_location, DexFile::GetDexCanonicalLocation(multidex_location_sym.c_str()));
386 
387   ASSERT_EQ(0, unlink(dex_location_sym.c_str()));
388 }
389 
TEST(DexFileUtilsTest,GetBaseLocationAndMultiDexSuffix)390 TEST(DexFileUtilsTest, GetBaseLocationAndMultiDexSuffix) {
391   EXPECT_EQ("/foo/bar/baz.jar", DexFile::GetBaseLocation("/foo/bar/baz.jar"));
392   EXPECT_EQ("/foo/bar/baz.jar", DexFile::GetBaseLocation("/foo/bar/baz.jar:classes2.dex"));
393   EXPECT_EQ("/foo/bar/baz.jar", DexFile::GetBaseLocation("/foo/bar/baz.jar:classes8.dex"));
394   EXPECT_EQ("", DexFile::GetMultiDexSuffix("/foo/bar/baz.jar"));
395   EXPECT_EQ(":classes2.dex", DexFile::GetMultiDexSuffix("/foo/bar/baz.jar:classes2.dex"));
396   EXPECT_EQ(":classes8.dex", DexFile::GetMultiDexSuffix("/foo/bar/baz.jar:classes8.dex"));
397 }
398 
399 }  // namespace art
400