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 "mem_map.h"
26 #include "os.h"
27 #include "scoped_thread_state_change-inl.h"
28 #include "thread-inl.h"
29 #include "utils.h"
30 
31 namespace art {
32 
33 class DexFileTest : public CommonRuntimeTest {};
34 
TEST_F(DexFileTest,Open)35 TEST_F(DexFileTest, Open) {
36   ScopedObjectAccess soa(Thread::Current());
37   std::unique_ptr<const DexFile> dex(OpenTestDexFile("Nested"));
38   ASSERT_TRUE(dex.get() != nullptr);
39 }
40 
DecodeBase64Vec(const char * src)41 static inline std::vector<uint8_t> DecodeBase64Vec(const char* src) {
42   std::vector<uint8_t> res;
43   size_t size;
44   std::unique_ptr<uint8_t[]> data(DecodeBase64(src, &size));
45   res.resize(size);
46   memcpy(res.data(), data.get(), size);
47   return res;
48 }
49 
50 // Although this is the same content logically as the Nested test dex,
51 // the DexFileHeader test is sensitive to subtle changes in the
52 // contents due to the checksum etc, so we embed the exact input here.
53 //
54 // class Nested {
55 //     class Inner {
56 //     }
57 // }
58 static const char kRawDex[] =
59   "ZGV4CjAzNQAQedgAe7gM1B/WHsWJ6L7lGAISGC7yjD2IAwAAcAAAAHhWNBIAAAAAAAAAAMQCAAAP"
60   "AAAAcAAAAAcAAACsAAAAAgAAAMgAAAABAAAA4AAAAAMAAADoAAAAAgAAAAABAABIAgAAQAEAAK4B"
61   "AAC2AQAAvQEAAM0BAADXAQAA+wEAABsCAAA+AgAAUgIAAF8CAABiAgAAZgIAAHMCAAB5AgAAgQIA"
62   "AAIAAAADAAAABAAAAAUAAAAGAAAABwAAAAkAAAAJAAAABgAAAAAAAAAKAAAABgAAAKgBAAAAAAEA"
63   "DQAAAAAAAQAAAAAAAQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAIAAAAiAEAAKsCAAAA"
64   "AAAAAQAAAAAAAAAFAAAAAAAAAAgAAACYAQAAuAIAAAAAAAACAAAAlAIAAJoCAAABAAAAowIAAAIA"
65   "AgABAAAAiAIAAAYAAABbAQAAcBACAAAADgABAAEAAQAAAI4CAAAEAAAAcBACAAAADgBAAQAAAAAA"
66   "AAAAAAAAAAAATAEAAAAAAAAAAAAAAAAAAAEAAAABAAY8aW5pdD4ABUlubmVyAA5MTmVzdGVkJElu"
67   "bmVyOwAITE5lc3RlZDsAIkxkYWx2aWsvYW5ub3RhdGlvbi9FbmNsb3NpbmdDbGFzczsAHkxkYWx2"
68   "aWsvYW5ub3RhdGlvbi9Jbm5lckNsYXNzOwAhTGRhbHZpay9hbm5vdGF0aW9uL01lbWJlckNsYXNz"
69   "ZXM7ABJMamF2YS9sYW5nL09iamVjdDsAC05lc3RlZC5qYXZhAAFWAAJWTAALYWNjZXNzRmxhZ3MA"
70   "BG5hbWUABnRoaXMkMAAFdmFsdWUAAgEABw4AAQAHDjwAAgIBDhgBAgMCCwQADBcBAgQBDhwBGAAA"
71   "AQEAAJAgAICABNQCAAABAAGAgATwAgAAEAAAAAAAAAABAAAAAAAAAAEAAAAPAAAAcAAAAAIAAAAH"
72   "AAAArAAAAAMAAAACAAAAyAAAAAQAAAABAAAA4AAAAAUAAAADAAAA6AAAAAYAAAACAAAAAAEAAAMQ"
73   "AAACAAAAQAEAAAEgAAACAAAAVAEAAAYgAAACAAAAiAEAAAEQAAABAAAAqAEAAAIgAAAPAAAArgEA"
74   "AAMgAAACAAAAiAIAAAQgAAADAAAAlAIAAAAgAAACAAAAqwIAAAAQAAABAAAAxAIAAA==";
75 
76 // kRawDex38 and 39 are dex'ed versions of the following Java source :
77 //
78 // public class Main {
79 //     public static void main(String[] foo) {
80 //     }
81 // }
82 //
83 // The dex file was manually edited to change its dex version code to 38
84 // or 39, respectively.
85 static const char kRawDex38[] =
86   "ZGV4CjAzOAC4OovJlJ1089ikzK6asMf/f8qp3Kve5VsgAgAAcAAAAHhWNBIAAAAAAAAAAIwBAAAI"
87   "AAAAcAAAAAQAAACQAAAAAgAAAKAAAAAAAAAAAAAAAAMAAAC4AAAAAQAAANAAAAAwAQAA8AAAACIB"
88   "AAAqAQAAMgEAAEYBAABRAQAAVAEAAFgBAABtAQAAAQAAAAIAAAAEAAAABgAAAAQAAAACAAAAAAAA"
89   "AAUAAAACAAAAHAEAAAAAAAAAAAAAAAABAAcAAAABAAAAAAAAAAAAAAABAAAAAQAAAAAAAAADAAAA"
90   "AAAAAH4BAAAAAAAAAQABAAEAAABzAQAABAAAAHAQAgAAAA4AAQABAAAAAAB4AQAAAQAAAA4AAAAB"
91   "AAAAAwAGPGluaXQ+AAZMTWFpbjsAEkxqYXZhL2xhbmcvT2JqZWN0OwAJTWFpbi5qYXZhAAFWAAJW"
92   "TAATW0xqYXZhL2xhbmcvU3RyaW5nOwAEbWFpbgABAAcOAAMBAAcOAAAAAgAAgYAE8AEBCYgCDAAA"
93   "AAAAAAABAAAAAAAAAAEAAAAIAAAAcAAAAAIAAAAEAAAAkAAAAAMAAAACAAAAoAAAAAUAAAADAAAA"
94   "uAAAAAYAAAABAAAA0AAAAAEgAAACAAAA8AAAAAEQAAABAAAAHAEAAAIgAAAIAAAAIgEAAAMgAAAC"
95   "AAAAcwEAAAAgAAABAAAAfgEAAAAQAAABAAAAjAEAAA==";
96 
97 static const char kRawDex39[] =
98   "ZGV4CjAzOQC4OovJlJ1089ikzK6asMf/f8qp3Kve5VsgAgAAcAAAAHhWNBIAAAAAAAAAAIwBAAAI"
99   "AAAAcAAAAAQAAACQAAAAAgAAAKAAAAAAAAAAAAAAAAMAAAC4AAAAAQAAANAAAAAwAQAA8AAAACIB"
100   "AAAqAQAAMgEAAEYBAABRAQAAVAEAAFgBAABtAQAAAQAAAAIAAAAEAAAABgAAAAQAAAACAAAAAAAA"
101   "AAUAAAACAAAAHAEAAAAAAAAAAAAAAAABAAcAAAABAAAAAAAAAAAAAAABAAAAAQAAAAAAAAADAAAA"
102   "AAAAAH4BAAAAAAAAAQABAAEAAABzAQAABAAAAHAQAgAAAA4AAQABAAAAAAB4AQAAAQAAAA4AAAAB"
103   "AAAAAwAGPGluaXQ+AAZMTWFpbjsAEkxqYXZhL2xhbmcvT2JqZWN0OwAJTWFpbi5qYXZhAAFWAAJW"
104   "TAATW0xqYXZhL2xhbmcvU3RyaW5nOwAEbWFpbgABAAcOAAMBAAcOAAAAAgAAgYAE8AEBCYgCDAAA"
105   "AAAAAAABAAAAAAAAAAEAAAAIAAAAcAAAAAIAAAAEAAAAkAAAAAMAAAACAAAAoAAAAAUAAAADAAAA"
106   "uAAAAAYAAAABAAAA0AAAAAEgAAACAAAA8AAAAAEQAAABAAAAHAEAAAIgAAAIAAAAIgEAAAMgAAAC"
107   "AAAAcwEAAAAgAAABAAAAfgEAAAAQAAABAAAAjAEAAA==";
108 
109 static const char kRawDexZeroLength[] =
110   "UEsDBAoAAAAAAOhxAkkAAAAAAAAAAAAAAAALABwAY2xhc3Nlcy5kZXhVVAkAA2QNoVdnDaFXdXgL"
111   "AAEE5AMBAASIEwAAUEsBAh4DCgAAAAAA6HECSQAAAAAAAAAAAAAAAAsAGAAAAAAAAAAAAKCBAAAA"
112   "AGNsYXNzZXMuZGV4VVQFAANkDaFXdXgLAAEE5AMBAASIEwAAUEsFBgAAAAABAAEAUQAAAEUAAAAA"
113   "AA==";
114 
115 static const char kRawZipClassesDexPresent[] =
116   "UEsDBBQAAAAIANVRN0ms99lIMQEAACACAAALABwAY2xhc3Nlcy5kZXhVVAkAAwFj5VcUY+VXdXgL"
117   "AAEE5AMBAASIEwAAS0mt4DIwtmDYYdV9csrcks83lpxZN2vD8f/1p1beWX3vabQCEwNDAQMDQ0WY"
118   "iRADFPQwMjBwMEDEWYB4AhADlTEsYEAAZiDeAcRApQwXgNgAyPgApJWAtBYQGwGxGxAHAnEIEEcA"
119   "cS4jRD0T1Fw2KM0ENZMVypZhRLIIqIMdag9CBMFnhtJ1jDA5RrBcMSPE7AIBkIl8UFGgP6Fu4IOa"
120   "wczAZpOZl1lix8Dm45uYmWfNIOSTlViWqJ+TmJeu75+UlZpcYs3ACZLSA4kzMIYxMIX5MAhHIykL"
121   "LinKzEu3ZmDJBSoDOZiPgRlMgv3T2MDygZGRs4OJB8n9MBoWzrAwmQD1Eyy8WZHCmg0pvBkVIGpA"
122   "Yc4oABEHhRuTAsRMUDwwQ9WAwoJBAaIGHE5Q9aB4BgBQSwECHgMUAAAACADVUTdJrPfZSDEBAAAg"
123   "AgAACwAYAAAAAAAAAAAAoIEAAAAAY2xhc3Nlcy5kZXhVVAUAAwFj5Vd1eAsAAQTkAwEABIgTAABQ"
124   "SwUGAAAAAAEAAQBRAAAAdgEAAAAA";
125 
126 static const char kRawZipClassesDexAbsent[] =
127   "UEsDBBQAAAAIANVRN0ms99lIMQEAACACAAAOABwAbm90Y2xhc3Nlcy5kZXhVVAkAAwFj5VcUY+VX"
128   "dXgLAAEE5AMBAASIEwAAS0mt4DIwtmDYYdV9csrcks83lpxZN2vD8f/1p1beWX3vabQCEwNDAQMD"
129   "Q0WYiRADFPQwMjBwMEDEWYB4AhADlTEsYEAAZiDeAcRApQwXgNgAyPgApJWAtBYQGwGxGxAHAnEI"
130   "EEcAcS4jRD0T1Fw2KM0ENZMVypZhRLIIqIMdag9CBMFnhtJ1jDA5RrBcMSPE7AIBkIl8UFGgP6Fu"
131   "4IOawczAZpOZl1lix8Dm45uYmWfNIOSTlViWqJ+TmJeu75+UlZpcYs3ACZLSA4kzMIYxMIX5MAhH"
132   "IykLLinKzEu3ZmDJBSoDOZiPgRlMgv3T2MDygZGRs4OJB8n9MBoWzrAwmQD1Eyy8WZHCmg0pvBkV"
133   "IGpAYc4oABEHhRuTAsRMUDwwQ9WAwoJBAaIGHE5Q9aB4BgBQSwECHgMUAAAACADVUTdJrPfZSDEB"
134   "AAAgAgAADgAYAAAAAAAAAAAAoIEAAAAAbm90Y2xhc3Nlcy5kZXhVVAUAAwFj5Vd1eAsAAQTkAwEA"
135   "BIgTAABQSwUGAAAAAAEAAQBUAAAAeQEAAAAA";
136 
137 static const char kRawZipThreeDexFiles[] =
138   "UEsDBBQAAAAIAP1WN0ms99lIMQEAACACAAAMABwAY2xhc3NlczIuZGV4VVQJAAOtbOVXrWzlV3V4"
139   "CwABBOQDAQAEiBMAAEtJreAyMLZg2GHVfXLK3JLPN5acWTdrw/H/9adW3ll972m0AhMDQwEDA0NF"
140   "mIkQAxT0MDIwcDBAxFmAeAIQA5UxLGBAAGYg3gHEQKUMF4DYAMj4AKSVgLQWEBsBsRsQBwJxCBBH"
141   "AHEuI0Q9E9RcNijNBDWTFcqWYUSyCKiDHWoPQgTBZ4bSdYwwOUawXDEjxOwCAZCJfFBRoD+hbuCD"
142   "msHMwGaTmZdZYsfA5uObmJlnzSDkk5VYlqifk5iXru+flJWaXGLNwAmS0gOJMzCGMTCF+TAIRyMp"
143   "Cy4pysxLt2ZgyQUqAzmYj4EZTIL909jA8oGRkbODiQfJ/TAaFs6wMJkA9RMsvFmRwpoNKbwZFSBq"
144   "QGHOKAARB4UbkwLETFA8MEPVgMKCQQGiBhxOUPWgeAYAUEsDBBQAAAAIAABXN0ms99lIMQEAACAC"
145   "AAAMABwAY2xhc3NlczMuZGV4VVQJAAOvbOVXr2zlV3V4CwABBOQDAQAEiBMAAEtJreAyMLZg2GHV"
146   "fXLK3JLPN5acWTdrw/H/9adW3ll972m0AhMDQwEDA0NFmIkQAxT0MDIwcDBAxFmAeAIQA5UxLGBA"
147   "AGYg3gHEQKUMF4DYAMj4AKSVgLQWEBsBsRsQBwJxCBBHAHEuI0Q9E9RcNijNBDWTFcqWYUSyCKiD"
148   "HWoPQgTBZ4bSdYwwOUawXDEjxOwCAZCJfFBRoD+hbuCDmsHMwGaTmZdZYsfA5uObmJlnzSDkk5VY"
149   "lqifk5iXru+flJWaXGLNwAmS0gOJMzCGMTCF+TAIRyMpCy4pysxLt2ZgyQUqAzmYj4EZTIL909jA"
150   "8oGRkbODiQfJ/TAaFs6wMJkA9RMsvFmRwpoNKbwZFSBqQGHOKAARB4UbkwLETFA8MEPVgMKCQQGi"
151   "BhxOUPWgeAYAUEsDBBQAAAAIANVRN0ms99lIMQEAACACAAALABwAY2xhc3Nlcy5kZXhVVAkAAwFj"
152   "5VetbOVXdXgLAAEE5AMBAASIEwAAS0mt4DIwtmDYYdV9csrcks83lpxZN2vD8f/1p1beWX3vabQC"
153   "EwNDAQMDQ0WYiRADFPQwMjBwMEDEWYB4AhADlTEsYEAAZiDeAcRApQwXgNgAyPgApJWAtBYQGwGx"
154   "GxAHAnEIEEcAcS4jRD0T1Fw2KM0ENZMVypZhRLIIqIMdag9CBMFnhtJ1jDA5RrBcMSPE7AIBkIl8"
155   "UFGgP6Fu4IOawczAZpOZl1lix8Dm45uYmWfNIOSTlViWqJ+TmJeu75+UlZpcYs3ACZLSA4kzMIYx"
156   "MIX5MAhHIykLLinKzEu3ZmDJBSoDOZiPgRlMgv3T2MDygZGRs4OJB8n9MBoWzrAwmQD1Eyy8WZHC"
157   "mg0pvBkVIGpAYc4oABEHhRuTAsRMUDwwQ9WAwoJBAaIGHE5Q9aB4BgBQSwECHgMUAAAACAD9VjdJ"
158   "rPfZSDEBAAAgAgAADAAYAAAAAAAAAAAAoIEAAAAAY2xhc3NlczIuZGV4VVQFAAOtbOVXdXgLAAEE"
159   "5AMBAASIEwAAUEsBAh4DFAAAAAgAAFc3Saz32UgxAQAAIAIAAAwAGAAAAAAAAAAAAKCBdwEAAGNs"
160   "YXNzZXMzLmRleFVUBQADr2zlV3V4CwABBOQDAQAEiBMAAFBLAQIeAxQAAAAIANVRN0ms99lIMQEA"
161   "ACACAAALABgAAAAAAAAAAACgge4CAABjbGFzc2VzLmRleFVUBQADAWPlV3V4CwABBOQDAQAEiBMA"
162   "AFBLBQYAAAAAAwADAPUAAABkBAAAAAA=";
163 
164 static const char kRawDexBadMapOffset[] =
165   "ZGV4CjAzNQAZKGSz85r+tXJ1I24FYi+FpQtWbXtelAmoAQAAcAAAAHhWNBIAAAAAAAAAAEAwIBAF"
166   "AAAAcAAAAAMAAACEAAAAAQAAAJAAAAAAAAAAAAAAAAIAAACcAAAAAQAAAKwAAADcAAAAzAAAAOQA"
167   "AADsAAAA9AAAAPkAAAANAQAAAgAAAAMAAAAEAAAABAAAAAIAAAAAAAAAAAAAAAAAAAABAAAAAAAA"
168   "AAAAAAABAAAAAQAAAAAAAAABAAAAAAAAABUBAAAAAAAAAQABAAEAAAAQAQAABAAAAHAQAQAAAA4A"
169   "Bjxpbml0PgAGQS5qYXZhAANMQTsAEkxqYXZhL2xhbmcvT2JqZWN0OwABVgABAAcOAAAAAQAAgYAE"
170   "zAEACwAAAAAAAAABAAAAAAAAAAEAAAAFAAAAcAAAAAIAAAADAAAAhAAAAAMAAAABAAAAkAAAAAUA"
171   "AAACAAAAnAAAAAYAAAABAAAArAAAAAEgAAABAAAAzAAAAAIgAAAFAAAA5AAAAAMgAAABAAAAEAEA"
172   "AAAgAAABAAAAFQEAAAAQAAABAAAAIAEAAA==";
173 
174 static const char kRawDexDebugInfoLocalNullType[] =
175     "ZGV4CjAzNQA+Kwj2g6OZMH88OvK9Ey6ycdIsFCt18ED8AQAAcAAAAHhWNBIAAAAAAAAAAHQBAAAI"
176     "AAAAcAAAAAQAAACQAAAAAgAAAKAAAAAAAAAAAAAAAAMAAAC4AAAAAQAAANAAAAAMAQAA8AAAABwB"
177     "AAAkAQAALAEAAC8BAAA0AQAASAEAAEsBAABOAQAAAgAAAAMAAAAEAAAABQAAAAIAAAAAAAAAAAAA"
178     "AAUAAAADAAAAAAAAAAEAAQAAAAAAAQAAAAYAAAACAAEAAAAAAAEAAAABAAAAAgAAAAAAAAABAAAA"
179     "AAAAAGMBAAAAAAAAAQABAAEAAABUAQAABAAAAHAQAgAAAA4AAgABAAAAAABZAQAAAgAAABIQDwAG"
180     "PGluaXQ+AAZBLmphdmEAAUkAA0xBOwASTGphdmEvbGFuZy9PYmplY3Q7AAFWAAFhAAR0aGlzAAEA"
181     "Bw4AAwAHDh4DAAcAAAAAAQEAgYAE8AEBAIgCAAAACwAAAAAAAAABAAAAAAAAAAEAAAAIAAAAcAAA"
182     "AAIAAAAEAAAAkAAAAAMAAAACAAAAoAAAAAUAAAADAAAAuAAAAAYAAAABAAAA0AAAAAEgAAACAAAA"
183     "8AAAAAIgAAAIAAAAHAEAAAMgAAACAAAAVAEAAAAgAAABAAAAYwEAAAAQAAABAAAAdAEAAA==";
184 
DecodeAndWriteDexFile(const char * base64,const char * location)185 static void DecodeAndWriteDexFile(const char* base64, const char* location) {
186   // decode base64
187   CHECK(base64 != nullptr);
188   std::vector<uint8_t> dex_bytes = DecodeBase64Vec(base64);
189   CHECK_NE(dex_bytes.size(), 0u);
190 
191   // write to provided file
192   std::unique_ptr<File> file(OS::CreateEmptyFile(location));
193   CHECK(file.get() != nullptr);
194   if (!file->WriteFully(dex_bytes.data(), dex_bytes.size())) {
195     PLOG(FATAL) << "Failed to write base64 as dex file";
196   }
197   if (file->FlushCloseOrErase() != 0) {
198     PLOG(FATAL) << "Could not flush and close test file.";
199   }
200 }
201 
OpenDexFilesBase64(const char * base64,const char * location,std::vector<std::unique_ptr<const DexFile>> * dex_files,std::string * error_msg)202 static bool OpenDexFilesBase64(const char* base64,
203                                const char* location,
204                                std::vector<std::unique_ptr<const DexFile>>* dex_files,
205                                std::string* error_msg) {
206   DecodeAndWriteDexFile(base64, location);
207 
208   // read dex file(s)
209   ScopedObjectAccess soa(Thread::Current());
210   static constexpr bool kVerifyChecksum = true;
211   std::vector<std::unique_ptr<const DexFile>> tmp;
212   bool success = DexFile::Open(location, location, kVerifyChecksum, error_msg, &tmp);
213   if (success) {
214     for (std::unique_ptr<const DexFile>& dex_file : tmp) {
215       EXPECT_EQ(PROT_READ, dex_file->GetPermissions());
216       EXPECT_TRUE(dex_file->IsReadOnly());
217     }
218     *dex_files = std::move(tmp);
219   }
220   return success;
221 }
222 
OpenDexFileBase64(const char * base64,const char * location)223 static std::unique_ptr<const DexFile> OpenDexFileBase64(const char* base64,
224                                                         const char* location) {
225   // read dex files.
226   std::string error_msg;
227   std::vector<std::unique_ptr<const DexFile>> dex_files;
228   bool success = OpenDexFilesBase64(base64, location, &dex_files, &error_msg);
229   CHECK(success) << error_msg;
230   EXPECT_EQ(1U, dex_files.size());
231   return std::move(dex_files[0]);
232 }
233 
OpenDexFileInMemoryBase64(const char * base64,const char * location,uint32_t location_checksum,bool expect_success)234 static std::unique_ptr<const DexFile> OpenDexFileInMemoryBase64(const char* base64,
235                                                                 const char* location,
236                                                                 uint32_t location_checksum,
237                                                                 bool expect_success) {
238   CHECK(base64 != nullptr);
239   std::vector<uint8_t> dex_bytes = DecodeBase64Vec(base64);
240   CHECK_NE(dex_bytes.size(), 0u);
241 
242   std::string error_message;
243   std::unique_ptr<MemMap> region(MemMap::MapAnonymous("test-region",
244                                                       nullptr,
245                                                       dex_bytes.size(),
246                                                       PROT_READ | PROT_WRITE,
247                                                       /* low_4gb */ false,
248                                                       /* reuse */ false,
249                                                       &error_message));
250   memcpy(region->Begin(), dex_bytes.data(), dex_bytes.size());
251   std::unique_ptr<const DexFile> dex_file(DexFile::Open(location,
252                                                         location_checksum,
253                                                         std::move(region),
254                                                         /* verify */ true,
255                                                         /* verify_checksum */ true,
256                                                         &error_message));
257   if (expect_success) {
258     CHECK(dex_file != nullptr) << error_message;
259   } else {
260     CHECK(dex_file == nullptr) << "Expected dex file open to fail.";
261   }
262   return dex_file;
263 }
264 
ValidateDexFileHeader(std::unique_ptr<const DexFile> dex_file)265 static void ValidateDexFileHeader(std::unique_ptr<const DexFile> dex_file) {
266   static const uint8_t kExpectedDexFileMagic[8] = {
267     /* d */ 0x64, /* e */ 0x64, /* x */ 0x78, /* \n */ 0x0d,
268     /* 0 */ 0x30, /* 3 */ 0x33, /* 5 */ 0x35, /* \0 */ 0x00
269   };
270   static const uint8_t kExpectedSha1[DexFile::kSha1DigestSize] = {
271     0x7b, 0xb8, 0x0c, 0xd4, 0x1f, 0xd6, 0x1e, 0xc5,
272     0x89, 0xe8, 0xbe, 0xe5, 0x18, 0x02, 0x12, 0x18,
273     0x2e, 0xf2, 0x8c, 0x3d,
274   };
275 
276   const DexFile::Header& header = dex_file->GetHeader();
277   EXPECT_EQ(*kExpectedDexFileMagic, *header.magic_);
278   EXPECT_EQ(0x00d87910U, header.checksum_);
279   EXPECT_EQ(*kExpectedSha1, *header.signature_);
280   EXPECT_EQ(904U, header.file_size_);
281   EXPECT_EQ(112U, header.header_size_);
282   EXPECT_EQ(0U, header.link_size_);
283   EXPECT_EQ(0U, header.link_off_);
284   EXPECT_EQ(15U, header.string_ids_size_);
285   EXPECT_EQ(112U, header.string_ids_off_);
286   EXPECT_EQ(7U, header.type_ids_size_);
287   EXPECT_EQ(172U, header.type_ids_off_);
288   EXPECT_EQ(2U, header.proto_ids_size_);
289   EXPECT_EQ(200U, header.proto_ids_off_);
290   EXPECT_EQ(1U, header.field_ids_size_);
291   EXPECT_EQ(224U, header.field_ids_off_);
292   EXPECT_EQ(3U, header.method_ids_size_);
293   EXPECT_EQ(232U, header.method_ids_off_);
294   EXPECT_EQ(2U, header.class_defs_size_);
295   EXPECT_EQ(256U, header.class_defs_off_);
296   EXPECT_EQ(584U, header.data_size_);
297   EXPECT_EQ(320U, header.data_off_);
298 
299   EXPECT_EQ(header.checksum_, dex_file->GetLocationChecksum());
300 }
301 
TEST_F(DexFileTest,Header)302 TEST_F(DexFileTest, Header) {
303   ScratchFile tmp;
304   std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kRawDex, tmp.GetFilename().c_str()));
305   ValidateDexFileHeader(std::move(raw));
306 }
307 
TEST_F(DexFileTest,HeaderInMemory)308 TEST_F(DexFileTest, HeaderInMemory) {
309   ScratchFile tmp;
310   std::unique_ptr<const DexFile> raw =
311       OpenDexFileInMemoryBase64(kRawDex, tmp.GetFilename().c_str(), 0x00d87910U, true);
312   ValidateDexFileHeader(std::move(raw));
313 }
314 
TEST_F(DexFileTest,Version38Accepted)315 TEST_F(DexFileTest, Version38Accepted) {
316   ScratchFile tmp;
317   std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kRawDex38, tmp.GetFilename().c_str()));
318   ASSERT_TRUE(raw.get() != nullptr);
319 
320   const DexFile::Header& header = raw->GetHeader();
321   EXPECT_EQ(38u, header.GetVersion());
322 }
323 
TEST_F(DexFileTest,Version39Rejected)324 TEST_F(DexFileTest, Version39Rejected) {
325   ScratchFile tmp;
326   const char* location = tmp.GetFilename().c_str();
327   DecodeAndWriteDexFile(kRawDex39, location);
328 
329   ScopedObjectAccess soa(Thread::Current());
330   static constexpr bool kVerifyChecksum = true;
331   std::string error_msg;
332   std::vector<std::unique_ptr<const DexFile>> dex_files;
333   ASSERT_FALSE(DexFile::Open(location, location, kVerifyChecksum, &error_msg, &dex_files));
334 }
335 
TEST_F(DexFileTest,ZeroLengthDexRejected)336 TEST_F(DexFileTest, ZeroLengthDexRejected) {
337   ScratchFile tmp;
338   const char* location = tmp.GetFilename().c_str();
339   DecodeAndWriteDexFile(kRawDexZeroLength, location);
340 
341   ScopedObjectAccess soa(Thread::Current());
342   static constexpr bool kVerifyChecksum = true;
343   std::string error_msg;
344   std::vector<std::unique_ptr<const DexFile>> dex_files;
345   ASSERT_FALSE(DexFile::Open(location, location, kVerifyChecksum, &error_msg, &dex_files));
346 }
347 
TEST_F(DexFileTest,GetLocationChecksum)348 TEST_F(DexFileTest, GetLocationChecksum) {
349   ScopedObjectAccess soa(Thread::Current());
350   std::unique_ptr<const DexFile> raw(OpenTestDexFile("Main"));
351   EXPECT_NE(raw->GetHeader().checksum_, raw->GetLocationChecksum());
352 }
353 
TEST_F(DexFileTest,GetChecksum)354 TEST_F(DexFileTest, GetChecksum) {
355   std::vector<uint32_t> checksums;
356   ScopedObjectAccess soa(Thread::Current());
357   std::string error_msg;
358   EXPECT_TRUE(DexFile::GetMultiDexChecksums(GetLibCoreDexFileNames()[0].c_str(), &checksums, &error_msg))
359       << error_msg;
360   ASSERT_EQ(1U, checksums.size());
361   EXPECT_EQ(java_lang_dex_file_->GetLocationChecksum(), checksums[0]);
362 }
363 
TEST_F(DexFileTest,GetMultiDexChecksums)364 TEST_F(DexFileTest, GetMultiDexChecksums) {
365   std::string error_msg;
366   std::vector<uint32_t> checksums;
367   std::string multidex_file = GetTestDexFileName("MultiDex");
368   EXPECT_TRUE(DexFile::GetMultiDexChecksums(multidex_file.c_str(),
369                                             &checksums,
370                                             &error_msg)) << error_msg;
371 
372   std::vector<std::unique_ptr<const DexFile>> dexes = OpenTestDexFiles("MultiDex");
373   ASSERT_EQ(2U, dexes.size());
374   ASSERT_EQ(2U, checksums.size());
375 
376   EXPECT_EQ(dexes[0]->GetLocation(), DexFile::GetMultiDexLocation(0, multidex_file.c_str()));
377   EXPECT_EQ(dexes[0]->GetLocationChecksum(), checksums[0]);
378 
379   EXPECT_EQ(dexes[1]->GetLocation(), DexFile::GetMultiDexLocation(1, multidex_file.c_str()));
380   EXPECT_EQ(dexes[1]->GetLocationChecksum(), checksums[1]);
381 }
382 
TEST_F(DexFileTest,ClassDefs)383 TEST_F(DexFileTest, ClassDefs) {
384   ScopedObjectAccess soa(Thread::Current());
385   std::unique_ptr<const DexFile> raw(OpenTestDexFile("Nested"));
386   ASSERT_TRUE(raw.get() != nullptr);
387   EXPECT_EQ(3U, raw->NumClassDefs());
388 
389   const DexFile::ClassDef& c0 = raw->GetClassDef(0);
390   EXPECT_STREQ("LNested$1;", raw->GetClassDescriptor(c0));
391 
392   const DexFile::ClassDef& c1 = raw->GetClassDef(1);
393   EXPECT_STREQ("LNested$Inner;", raw->GetClassDescriptor(c1));
394 
395   const DexFile::ClassDef& c2 = raw->GetClassDef(2);
396   EXPECT_STREQ("LNested;", raw->GetClassDescriptor(c2));
397 }
398 
TEST_F(DexFileTest,GetMethodSignature)399 TEST_F(DexFileTest, GetMethodSignature) {
400   ScopedObjectAccess soa(Thread::Current());
401   std::unique_ptr<const DexFile> raw(OpenTestDexFile("GetMethodSignature"));
402   ASSERT_TRUE(raw.get() != nullptr);
403   EXPECT_EQ(1U, raw->NumClassDefs());
404 
405   const DexFile::ClassDef& class_def = raw->GetClassDef(0);
406   ASSERT_STREQ("LGetMethodSignature;", raw->GetClassDescriptor(class_def));
407 
408   const uint8_t* class_data = raw->GetClassData(class_def);
409   ASSERT_TRUE(class_data != nullptr);
410   ClassDataItemIterator it(*raw, class_data);
411 
412   EXPECT_EQ(1u, it.NumDirectMethods());
413 
414   // Check the signature for the static initializer.
415   {
416     ASSERT_EQ(1U, it.NumDirectMethods());
417     const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex());
418     const char* name = raw->StringDataByIdx(method_id.name_idx_);
419     ASSERT_STREQ("<init>", name);
420     std::string signature(raw->GetMethodSignature(method_id).ToString());
421     ASSERT_EQ("()V", signature);
422   }
423 
424   // Check both virtual methods.
425   ASSERT_EQ(2U, it.NumVirtualMethods());
426   {
427     it.Next();
428     const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex());
429 
430     const char* name = raw->StringDataByIdx(method_id.name_idx_);
431     ASSERT_STREQ("m1", name);
432 
433     std::string signature(raw->GetMethodSignature(method_id).ToString());
434     ASSERT_EQ("(IDJLjava/lang/Object;)Ljava/lang/Float;", signature);
435   }
436 
437   {
438     it.Next();
439     const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex());
440 
441     const char* name = raw->StringDataByIdx(method_id.name_idx_);
442     ASSERT_STREQ("m2", name);
443 
444     std::string signature(raw->GetMethodSignature(method_id).ToString());
445     ASSERT_EQ("(ZSC)LGetMethodSignature;", signature);
446   }
447 }
448 
TEST_F(DexFileTest,FindStringId)449 TEST_F(DexFileTest, FindStringId) {
450   ScopedObjectAccess soa(Thread::Current());
451   std::unique_ptr<const DexFile> raw(OpenTestDexFile("GetMethodSignature"));
452   ASSERT_TRUE(raw.get() != nullptr);
453   EXPECT_EQ(1U, raw->NumClassDefs());
454 
455   const char* strings[] = { "LGetMethodSignature;", "Ljava/lang/Float;", "Ljava/lang/Object;",
456       "D", "I", "J", nullptr };
457   for (size_t i = 0; strings[i] != nullptr; i++) {
458     const char* str = strings[i];
459     const DexFile::StringId* str_id = raw->FindStringId(str);
460     const char* dex_str = raw->GetStringData(*str_id);
461     EXPECT_STREQ(dex_str, str);
462   }
463 }
464 
TEST_F(DexFileTest,FindTypeId)465 TEST_F(DexFileTest, FindTypeId) {
466   for (size_t i = 0; i < java_lang_dex_file_->NumTypeIds(); i++) {
467     const char* type_str = java_lang_dex_file_->StringByTypeIdx(dex::TypeIndex(i));
468     const DexFile::StringId* type_str_id = java_lang_dex_file_->FindStringId(type_str);
469     ASSERT_TRUE(type_str_id != nullptr);
470     dex::StringIndex type_str_idx = java_lang_dex_file_->GetIndexForStringId(*type_str_id);
471     const DexFile::TypeId* type_id = java_lang_dex_file_->FindTypeId(type_str_idx);
472     ASSERT_EQ(type_id, java_lang_dex_file_->FindTypeId(type_str));
473     ASSERT_TRUE(type_id != nullptr);
474     EXPECT_EQ(java_lang_dex_file_->GetIndexForTypeId(*type_id).index_, i);
475   }
476 }
477 
TEST_F(DexFileTest,FindProtoId)478 TEST_F(DexFileTest, FindProtoId) {
479   for (size_t i = 0; i < java_lang_dex_file_->NumProtoIds(); i++) {
480     const DexFile::ProtoId& to_find = java_lang_dex_file_->GetProtoId(i);
481     const DexFile::TypeList* to_find_tl = java_lang_dex_file_->GetProtoParameters(to_find);
482     std::vector<dex::TypeIndex> to_find_types;
483     if (to_find_tl != nullptr) {
484       for (size_t j = 0; j < to_find_tl->Size(); j++) {
485         to_find_types.push_back(to_find_tl->GetTypeItem(j).type_idx_);
486       }
487     }
488     const DexFile::ProtoId* found =
489         java_lang_dex_file_->FindProtoId(to_find.return_type_idx_, to_find_types);
490     ASSERT_TRUE(found != nullptr);
491     EXPECT_EQ(java_lang_dex_file_->GetIndexForProtoId(*found), i);
492   }
493 }
494 
TEST_F(DexFileTest,FindMethodId)495 TEST_F(DexFileTest, FindMethodId) {
496   for (size_t i = 0; i < java_lang_dex_file_->NumMethodIds(); i++) {
497     const DexFile::MethodId& to_find = java_lang_dex_file_->GetMethodId(i);
498     const DexFile::TypeId& klass = java_lang_dex_file_->GetTypeId(to_find.class_idx_);
499     const DexFile::StringId& name = java_lang_dex_file_->GetStringId(to_find.name_idx_);
500     const DexFile::ProtoId& signature = java_lang_dex_file_->GetProtoId(to_find.proto_idx_);
501     const DexFile::MethodId* found = java_lang_dex_file_->FindMethodId(klass, name, signature);
502     ASSERT_TRUE(found != nullptr) << "Didn't find method " << i << ": "
503         << java_lang_dex_file_->StringByTypeIdx(to_find.class_idx_) << "."
504         << java_lang_dex_file_->GetStringData(name)
505         << java_lang_dex_file_->GetMethodSignature(to_find);
506     EXPECT_EQ(java_lang_dex_file_->GetIndexForMethodId(*found), i);
507   }
508 }
509 
TEST_F(DexFileTest,FindFieldId)510 TEST_F(DexFileTest, FindFieldId) {
511   for (size_t i = 0; i < java_lang_dex_file_->NumFieldIds(); i++) {
512     const DexFile::FieldId& to_find = java_lang_dex_file_->GetFieldId(i);
513     const DexFile::TypeId& klass = java_lang_dex_file_->GetTypeId(to_find.class_idx_);
514     const DexFile::StringId& name = java_lang_dex_file_->GetStringId(to_find.name_idx_);
515     const DexFile::TypeId& type = java_lang_dex_file_->GetTypeId(to_find.type_idx_);
516     const DexFile::FieldId* found = java_lang_dex_file_->FindFieldId(klass, name, type);
517     ASSERT_TRUE(found != nullptr) << "Didn't find field " << i << ": "
518         << java_lang_dex_file_->StringByTypeIdx(to_find.type_idx_) << " "
519         << java_lang_dex_file_->StringByTypeIdx(to_find.class_idx_) << "."
520         << java_lang_dex_file_->GetStringData(name);
521     EXPECT_EQ(java_lang_dex_file_->GetIndexForFieldId(*found), i);
522   }
523 }
524 
TEST_F(DexFileTest,GetMultiDexClassesDexName)525 TEST_F(DexFileTest, GetMultiDexClassesDexName) {
526   ASSERT_EQ("classes.dex", DexFile::GetMultiDexClassesDexName(0));
527   ASSERT_EQ("classes2.dex", DexFile::GetMultiDexClassesDexName(1));
528   ASSERT_EQ("classes3.dex", DexFile::GetMultiDexClassesDexName(2));
529   ASSERT_EQ("classes100.dex", DexFile::GetMultiDexClassesDexName(99));
530 }
531 
TEST_F(DexFileTest,GetMultiDexLocation)532 TEST_F(DexFileTest, GetMultiDexLocation) {
533   std::string dex_location_str = "/system/app/framework.jar";
534   const char* dex_location = dex_location_str.c_str();
535   ASSERT_EQ("/system/app/framework.jar", DexFile::GetMultiDexLocation(0, dex_location));
536   ASSERT_EQ("/system/app/framework.jar:classes2.dex",
537             DexFile::GetMultiDexLocation(1, dex_location));
538   ASSERT_EQ("/system/app/framework.jar:classes101.dex",
539             DexFile::GetMultiDexLocation(100, dex_location));
540 }
541 
TEST_F(DexFileTest,GetDexCanonicalLocation)542 TEST_F(DexFileTest, GetDexCanonicalLocation) {
543   ScratchFile file;
544   UniqueCPtr<const char[]> dex_location_real(realpath(file.GetFilename().c_str(), nullptr));
545   std::string dex_location(dex_location_real.get());
546 
547   ASSERT_EQ(dex_location, DexFile::GetDexCanonicalLocation(dex_location.c_str()));
548   std::string multidex_location = DexFile::GetMultiDexLocation(1, dex_location.c_str());
549   ASSERT_EQ(multidex_location, DexFile::GetDexCanonicalLocation(multidex_location.c_str()));
550 
551   std::string dex_location_sym = dex_location + "symlink";
552   ASSERT_EQ(0, symlink(dex_location.c_str(), dex_location_sym.c_str()));
553 
554   ASSERT_EQ(dex_location, DexFile::GetDexCanonicalLocation(dex_location_sym.c_str()));
555 
556   std::string multidex_location_sym = DexFile::GetMultiDexLocation(1, dex_location_sym.c_str());
557   ASSERT_EQ(multidex_location, DexFile::GetDexCanonicalLocation(multidex_location_sym.c_str()));
558 
559   ASSERT_EQ(0, unlink(dex_location_sym.c_str()));
560 }
561 
TEST(DexFileUtilsTest,GetBaseLocationAndMultiDexSuffix)562 TEST(DexFileUtilsTest, GetBaseLocationAndMultiDexSuffix) {
563   EXPECT_EQ("/foo/bar/baz.jar", DexFile::GetBaseLocation("/foo/bar/baz.jar"));
564   EXPECT_EQ("/foo/bar/baz.jar", DexFile::GetBaseLocation("/foo/bar/baz.jar:classes2.dex"));
565   EXPECT_EQ("/foo/bar/baz.jar", DexFile::GetBaseLocation("/foo/bar/baz.jar:classes8.dex"));
566   EXPECT_EQ("", DexFile::GetMultiDexSuffix("/foo/bar/baz.jar"));
567   EXPECT_EQ(":classes2.dex", DexFile::GetMultiDexSuffix("/foo/bar/baz.jar:classes2.dex"));
568   EXPECT_EQ(":classes8.dex", DexFile::GetMultiDexSuffix("/foo/bar/baz.jar:classes8.dex"));
569 }
570 
TEST_F(DexFileTest,ZipOpenClassesPresent)571 TEST_F(DexFileTest, ZipOpenClassesPresent) {
572   ScratchFile tmp;
573   std::vector<std::unique_ptr<const DexFile>> dex_files;
574   std::string error_msg;
575   ASSERT_TRUE(OpenDexFilesBase64(kRawZipClassesDexPresent, tmp.GetFilename().c_str(), &dex_files,
576                                  &error_msg));
577   EXPECT_EQ(dex_files.size(), 1u);
578 }
579 
TEST_F(DexFileTest,ZipOpenClassesAbsent)580 TEST_F(DexFileTest, ZipOpenClassesAbsent) {
581   ScratchFile tmp;
582   std::vector<std::unique_ptr<const DexFile>> dex_files;
583   std::string error_msg;
584   ASSERT_FALSE(OpenDexFilesBase64(kRawZipClassesDexAbsent, tmp.GetFilename().c_str(), &dex_files,
585                                   &error_msg));
586   EXPECT_EQ(dex_files.size(), 0u);
587 }
588 
TEST_F(DexFileTest,ZipOpenThreeDexFiles)589 TEST_F(DexFileTest, ZipOpenThreeDexFiles) {
590   ScratchFile tmp;
591   std::vector<std::unique_ptr<const DexFile>> dex_files;
592   std::string error_msg;
593   ASSERT_TRUE(OpenDexFilesBase64(kRawZipThreeDexFiles, tmp.GetFilename().c_str(), &dex_files,
594                                  &error_msg));
595   EXPECT_EQ(dex_files.size(), 3u);
596 }
597 
TEST_F(DexFileTest,OpenDexBadMapOffset)598 TEST_F(DexFileTest, OpenDexBadMapOffset) {
599   ScratchFile tmp;
600   std::unique_ptr<const DexFile> raw =
601       OpenDexFileInMemoryBase64(kRawDexBadMapOffset, tmp.GetFilename().c_str(), 0xb3642819U, false);
602   EXPECT_EQ(raw, nullptr);
603 }
604 
TEST_F(DexFileTest,GetStringWithNoIndex)605 TEST_F(DexFileTest, GetStringWithNoIndex) {
606   ScratchFile tmp;
607   std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kRawDex, tmp.GetFilename().c_str()));
608   dex::TypeIndex idx;
609   EXPECT_EQ(raw->StringByTypeIdx(idx), nullptr);
610 }
611 
Callback(void * context ATTRIBUTE_UNUSED,const DexFile::LocalInfo & entry ATTRIBUTE_UNUSED)612 static void Callback(void* context ATTRIBUTE_UNUSED,
613                      const DexFile::LocalInfo& entry ATTRIBUTE_UNUSED) {
614 }
615 
TEST_F(DexFileTest,OpenDexDebugInfoLocalNullType)616 TEST_F(DexFileTest, OpenDexDebugInfoLocalNullType) {
617   ScratchFile tmp;
618   std::unique_ptr<const DexFile> raw = OpenDexFileInMemoryBase64(
619       kRawDexDebugInfoLocalNullType, tmp.GetFilename().c_str(), 0xf25f2b38U, true);
620   const DexFile::ClassDef& class_def = raw->GetClassDef(0);
621   const DexFile::CodeItem* code_item = raw->GetCodeItem(raw->FindCodeItemOffset(class_def, 1));
622   ASSERT_TRUE(raw->DecodeDebugLocalInfo(code_item, true, 1, Callback, nullptr));
623 }
624 
625 }  // namespace art
626