1 /*
2  * Copyright (C) 2019 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 <sys/types.h>
18 
19 #include <memory>
20 #include <string>
21 #include <string_view>
22 
23 #include <android-base/file.h>
24 #include <dex/dex_file.h>
25 #include <gtest/gtest.h>
26 
27 #include "art_api/dex_file_support.h"
28 
29 namespace art_api {
30 namespace dex {
31 
32 static constexpr uint32_t kDexData[] = {
33     0x0a786564, 0x00383330, 0xc98b3ab8, 0xf3749d94, 0xaecca4d8, 0xffc7b09a, 0xdca9ca7f, 0x5be5deab,
34     0x00000220, 0x00000070, 0x12345678, 0x00000000, 0x00000000, 0x0000018c, 0x00000008, 0x00000070,
35     0x00000004, 0x00000090, 0x00000002, 0x000000a0, 0x00000000, 0x00000000, 0x00000003, 0x000000b8,
36     0x00000001, 0x000000d0, 0x00000130, 0x000000f0, 0x00000122, 0x0000012a, 0x00000132, 0x00000146,
37     0x00000151, 0x00000154, 0x00000158, 0x0000016d, 0x00000001, 0x00000002, 0x00000004, 0x00000006,
38     0x00000004, 0x00000002, 0x00000000, 0x00000005, 0x00000002, 0x0000011c, 0x00000000, 0x00000000,
39     0x00010000, 0x00000007, 0x00000001, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000,
40     0x00000003, 0x00000000, 0x0000017e, 0x00000000, 0x00010001, 0x00000001, 0x00000173, 0x00000004,
41     0x00021070, 0x000e0000, 0x00010001, 0x00000000, 0x00000178, 0x00000001, 0x0000000e, 0x00000001,
42     0x3c060003, 0x74696e69, 0x4c06003e, 0x6e69614d, 0x4c12003b, 0x6176616a, 0x6e616c2f, 0x624f2f67,
43     0x7463656a, 0x4d09003b, 0x2e6e6961, 0x6176616a, 0x00560100, 0x004c5602, 0x6a4c5b13, 0x2f617661,
44     0x676e616c, 0x7274532f, 0x3b676e69, 0x616d0400, 0x01006e69, 0x000e0700, 0x07000103, 0x0000000e,
45     0x81000002, 0x01f00480, 0x02880901, 0x0000000c, 0x00000000, 0x00000001, 0x00000000, 0x00000001,
46     0x00000008, 0x00000070, 0x00000002, 0x00000004, 0x00000090, 0x00000003, 0x00000002, 0x000000a0,
47     0x00000005, 0x00000003, 0x000000b8, 0x00000006, 0x00000001, 0x000000d0, 0x00002001, 0x00000002,
48     0x000000f0, 0x00001001, 0x00000001, 0x0000011c, 0x00002002, 0x00000008, 0x00000122, 0x00002003,
49     0x00000002, 0x00000173, 0x00002000, 0x00000001, 0x0000017e, 0x00001000, 0x00000001, 0x0000018c,
50 };
51 
TEST(DexStringTest,alloc_string)52 TEST(DexStringTest, alloc_string) {
53   auto s = DexString("123");
54   EXPECT_EQ(std::string_view(s), "123");
55 }
56 
TEST(DexStringTest,alloc_empty_string)57 TEST(DexStringTest, alloc_empty_string) {
58   auto s = DexString("");
59   EXPECT_TRUE(std::string_view(s).empty());
60 }
61 
TEST(DexStringTest,move_construct)62 TEST(DexStringTest, move_construct) {
63   auto s1 = DexString("foo");
64   auto s2 = DexString(std::move(s1));
65   EXPECT_TRUE(std::string_view(s1).empty()); // NOLINT bugprone-use-after-move
66   EXPECT_EQ(std::string_view(s2), "foo");
67 }
68 
TEST(DexStringTest,move_assign)69 TEST(DexStringTest, move_assign) {
70   auto s1 = DexString("foo");
71   DexString s2;
72   EXPECT_TRUE(std::string_view(s2).empty());
73   s2 = std::move(s1);
74   EXPECT_TRUE(std::string_view(s1).empty()); // NOLINT bugprone-use-after-move
75   EXPECT_EQ(std::string_view(s2), "foo");
76 }
77 
TEST(DexStringTest,reassign)78 TEST(DexStringTest, reassign) {
79   auto s = DexString("foo");
80   s = DexString("bar");
81   EXPECT_EQ(std::string_view(s), "bar");
82 }
83 
TEST(DexStringTest,data_access)84 TEST(DexStringTest, data_access) {
85   auto s = DexString("foo");
86   EXPECT_STREQ(s.data(), "foo");
87   EXPECT_STREQ(s.c_str(), "foo");
88 }
89 
TEST(DexStringTest,size_access)90 TEST(DexStringTest, size_access) {
91   auto s = DexString("foo");
92   EXPECT_EQ(s.size(), size_t{3});
93   EXPECT_EQ(s.length(), size_t{3});
94 }
95 
TEST(DexStringTest,equality)96 TEST(DexStringTest, equality) {
97   auto s = DexString("foo");
98   EXPECT_EQ(s, DexString("foo"));
99   EXPECT_FALSE(s == DexString("bar"));
100 }
101 
TEST(DexStringTest,equality_with_nul)102 TEST(DexStringTest, equality_with_nul) {
103   auto s = DexString(std::string("foo\0bar", 7));
104   EXPECT_EQ(s.size(), size_t{7});
105   EXPECT_EQ(s, DexString(std::string("foo\0bar", 7)));
106   EXPECT_FALSE(s == DexString(std::string("foo\0baz", 7)));
107 }
108 
TEST(DexFileTest,from_memory_header_too_small)109 TEST(DexFileTest, from_memory_header_too_small) {
110   size_t size = sizeof(art::DexFile::Header) - 1;
111   std::string error_msg;
112   EXPECT_EQ(DexFile::OpenFromMemory(kDexData, &size, "", &error_msg), nullptr);
113   EXPECT_EQ(size, sizeof(art::DexFile::Header));
114   EXPECT_TRUE(error_msg.empty());
115 }
116 
TEST(DexFileTest,from_memory_file_too_small)117 TEST(DexFileTest, from_memory_file_too_small) {
118   size_t size = sizeof(art::DexFile::Header);
119   std::string error_msg;
120   EXPECT_EQ(DexFile::OpenFromMemory(kDexData, &size, "", &error_msg), nullptr);
121   EXPECT_EQ(size, sizeof(kDexData));
122   EXPECT_TRUE(error_msg.empty());
123 }
124 
GetTestDexData()125 static std::unique_ptr<DexFile> GetTestDexData() {
126   size_t size = sizeof(kDexData);
127   std::string error_msg;
128   std::unique_ptr<DexFile> dex_file = DexFile::OpenFromMemory(kDexData, &size, "", &error_msg);
129   EXPECT_TRUE(error_msg.empty());
130   return dex_file;
131 }
132 
TEST(DexFileTest,from_memory)133 TEST(DexFileTest, from_memory) {
134   EXPECT_NE(GetTestDexData(), nullptr);
135 }
136 
TEST(DexFileTest,from_fd_header_too_small)137 TEST(DexFileTest, from_fd_header_too_small) {
138   TemporaryFile tf;
139   ASSERT_NE(tf.fd, -1);
140   ASSERT_EQ(sizeof(art::DexFile::Header) - 1,
141             static_cast<size_t>(
142                 TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(art::DexFile::Header) - 1))));
143 
144   std::string error_msg;
145   EXPECT_EQ(DexFile::OpenFromFd(tf.fd, 0, tf.path, &error_msg), nullptr);
146   EXPECT_FALSE(error_msg.empty());
147 }
148 
TEST(DexFileTest,from_fd_file_too_small)149 TEST(DexFileTest, from_fd_file_too_small) {
150   TemporaryFile tf;
151   ASSERT_NE(tf.fd, -1);
152   ASSERT_EQ(sizeof(art::DexFile::Header),
153             static_cast<size_t>(
154                 TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(art::DexFile::Header)))));
155 
156   std::string error_msg;
157   EXPECT_EQ(DexFile::OpenFromFd(tf.fd, 0, tf.path, &error_msg), nullptr);
158   EXPECT_FALSE(error_msg.empty());
159 }
160 
TEST(DexFileTest,from_fd)161 TEST(DexFileTest, from_fd) {
162   TemporaryFile tf;
163   ASSERT_NE(tf.fd, -1);
164   ASSERT_EQ(sizeof(kDexData),
165             static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
166 
167   std::string error_msg;
168   EXPECT_NE(DexFile::OpenFromFd(tf.fd, 0, tf.path, &error_msg), nullptr);
169   EXPECT_TRUE(error_msg.empty());
170 }
171 
TEST(DexFileTest,from_fd_non_zero_offset)172 TEST(DexFileTest, from_fd_non_zero_offset) {
173   TemporaryFile tf;
174   ASSERT_NE(tf.fd, -1);
175   ASSERT_EQ(0x100, lseek(tf.fd, 0x100, SEEK_SET));
176   ASSERT_EQ(sizeof(kDexData),
177             static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
178 
179   std::string error_msg;
180   EXPECT_NE(DexFile::OpenFromFd(tf.fd, 0x100, tf.path, &error_msg), nullptr);
181   EXPECT_TRUE(error_msg.empty());
182 }
183 
TEST(DexFileTest,get_method_info_for_offset_without_signature)184 TEST(DexFileTest, get_method_info_for_offset_without_signature) {
185   std::unique_ptr<DexFile> dex_file = GetTestDexData();
186   ASSERT_NE(dex_file, nullptr);
187 
188   MethodInfo info = dex_file->GetMethodInfoForOffset(0x102, false);
189   EXPECT_EQ(info.offset, int32_t{0x100});
190   EXPECT_EQ(info.len, int32_t{8});
191   EXPECT_STREQ(info.name.data(), "Main.<init>");
192 
193   info = dex_file->GetMethodInfoForOffset(0x118, false);
194   EXPECT_EQ(info.offset, int32_t{0x118});
195   EXPECT_EQ(info.len, int32_t{2});
196   EXPECT_STREQ(info.name.data(), "Main.main");
197 
198   // Retrieve a cached result.
199   info = dex_file->GetMethodInfoForOffset(0x104, false);
200   EXPECT_EQ(info.offset, int32_t{0x100});
201   EXPECT_EQ(info.len, int32_t{8});
202   EXPECT_STREQ(info.name.data(), "Main.<init>");
203 }
204 
TEST(DexFileTest,get_method_info_for_offset_with_signature)205 TEST(DexFileTest, get_method_info_for_offset_with_signature) {
206   std::unique_ptr<DexFile> dex_file = GetTestDexData();
207   ASSERT_NE(dex_file, nullptr);
208 
209   MethodInfo info = dex_file->GetMethodInfoForOffset(0x102, true);
210   EXPECT_EQ(info.offset, int32_t{0x100});
211   EXPECT_EQ(info.len, int32_t{8});
212   EXPECT_STREQ(info.name.data(), "void Main.<init>()");
213 
214   info = dex_file->GetMethodInfoForOffset(0x118, true);
215   EXPECT_EQ(info.offset, int32_t{0x118});
216   EXPECT_EQ(info.len, int32_t{2});
217   EXPECT_STREQ(info.name.data(), "void Main.main(java.lang.String[])");
218 
219   // Retrieve a cached result.
220   info = dex_file->GetMethodInfoForOffset(0x104, true);
221   EXPECT_EQ(info.offset, int32_t{0x100});
222   EXPECT_EQ(info.len, int32_t{8});
223   EXPECT_STREQ(info.name.data(), "void Main.<init>()");
224 
225   // with_signature doesn't affect the cache.
226   info = dex_file->GetMethodInfoForOffset(0x104, false);
227   EXPECT_EQ(info.offset, int32_t{0x100});
228   EXPECT_EQ(info.len, int32_t{8});
229   EXPECT_STREQ(info.name.data(), "Main.<init>");
230 }
231 
TEST(DexFileTest,get_method_info_for_offset_boundaries)232 TEST(DexFileTest, get_method_info_for_offset_boundaries) {
233   std::unique_ptr<DexFile> dex_file = GetTestDexData();
234   ASSERT_NE(dex_file, nullptr);
235 
236   MethodInfo info = dex_file->GetMethodInfoForOffset(0x100000, false);
237   EXPECT_EQ(info.offset, int32_t{0});
238 
239   info = dex_file->GetMethodInfoForOffset(0x99, false);
240   EXPECT_EQ(info.offset, int32_t{0});
241   info = dex_file->GetMethodInfoForOffset(0x100, false);
242   EXPECT_EQ(info.offset, int32_t{0x100});
243   info = dex_file->GetMethodInfoForOffset(0x107, false);
244   EXPECT_EQ(info.offset, int32_t{0x100});
245   info = dex_file->GetMethodInfoForOffset(0x108, false);
246   EXPECT_EQ(info.offset, int32_t{0});
247 
248   // Make sure that once the whole dex file has been cached, no problems occur.
249   info = dex_file->GetMethodInfoForOffset(0x98, false);
250   EXPECT_EQ(info.offset, int32_t{0});
251 
252   // Choose a value that is in the cached map, but not in a valid method.
253   info = dex_file->GetMethodInfoForOffset(0x110, false);
254   EXPECT_EQ(info.offset, int32_t{0});
255 }
256 
TEST(DexFileTest,get_all_method_infos_without_signature)257 TEST(DexFileTest, get_all_method_infos_without_signature) {
258   std::unique_ptr<DexFile> dex_file = GetTestDexData();
259   ASSERT_NE(dex_file, nullptr);
260 
261   std::vector<MethodInfo> infos;
262   infos.emplace_back(MethodInfo{0x100, 8, DexString("Main.<init>")});
263   infos.emplace_back(MethodInfo{0x118, 2, DexString("Main.main")});
264   ASSERT_EQ(dex_file->GetAllMethodInfos(false), infos);
265 }
266 
TEST(DexFileTest,get_all_method_infos_with_signature)267 TEST(DexFileTest, get_all_method_infos_with_signature) {
268   std::unique_ptr<DexFile> dex_file = GetTestDexData();
269   ASSERT_NE(dex_file, nullptr);
270 
271   std::vector<MethodInfo> infos;
272   infos.emplace_back(MethodInfo{0x100, 8, DexString("void Main.<init>()")});
273   infos.emplace_back(MethodInfo{0x118, 2, DexString("void Main.main(java.lang.String[])")});
274   ASSERT_EQ(dex_file->GetAllMethodInfos(true), infos);
275 }
276 
TEST(DexFileTest,move_construct)277 TEST(DexFileTest, move_construct) {
278   std::unique_ptr<DexFile> dex_file = GetTestDexData();
279   ASSERT_NE(dex_file, nullptr);
280 
281   auto df1 = DexFile(std::move(*dex_file));
282   auto df2 = DexFile(std::move(df1));
283 
284   MethodInfo info = df2.GetMethodInfoForOffset(0x100, false);
285   EXPECT_EQ(info.offset, int32_t{0x100});
286 }
287 
TEST(DexFileTest,pointer_construct)288 TEST(DexFileTest, pointer_construct) {
289   std::unique_ptr<DexFile> dex_file = GetTestDexData();
290   ASSERT_NE(dex_file, nullptr);
291 
292   auto new_dex = DexFile(dex_file);
293   ASSERT_TRUE(dex_file.get() == nullptr);
294 
295   MethodInfo info = new_dex.GetMethodInfoForOffset(0x100, false);
296   EXPECT_EQ(info.offset, int32_t{0x100});
297 }
298 
299 }  // namespace dex
300 }  // namespace art_api
301