blob: e39287018ad90b4de0a87fb5c40bec3a739fbda3 [file] [log] [blame]
Andreas Gampedf10b322014-06-11 21:46:05 -07001/*
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_verifier.h"
18
Ian Rogerse63db272014-07-15 15:36:11 -070019#include "sys/mman.h"
Andreas Gampedf10b322014-06-11 21:46:05 -070020#include "zlib.h"
Andreas Gampee6215c02015-08-31 18:54:38 -070021#include <functional>
Ian Rogerse63db272014-07-15 15:36:11 -070022#include <memory>
Andreas Gampedf10b322014-06-11 21:46:05 -070023
Ian Rogerse63db272014-07-15 15:36:11 -070024#include "base/unix_file/fd_file.h"
Andreas Gampee6215c02015-08-31 18:54:38 -070025#include "base/bit_utils.h"
Andreas Gampedf10b322014-06-11 21:46:05 -070026#include "base/macros.h"
Ian Rogerse63db272014-07-15 15:36:11 -070027#include "common_runtime_test.h"
Andreas Gampee6215c02015-08-31 18:54:38 -070028#include "dex_file-inl.h"
29#include "leb128.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070030#include "scoped_thread_state_change-inl.h"
Ian Rogerse63db272014-07-15 15:36:11 -070031#include "thread-inl.h"
Alex Light9c20a142016-08-23 15:05:12 -070032#include "utils.h"
Andreas Gampedf10b322014-06-11 21:46:05 -070033
34namespace art {
35
Alex Light0ed05212016-05-06 17:36:36 -070036// Make the Dex file version 37.
37static void MakeDexVersion37(DexFile* dex_file) {
38 size_t offset = OFFSETOF_MEMBER(DexFile::Header, magic_) + 6;
39 CHECK_EQ(*(dex_file->Begin() + offset), '5');
40 *(const_cast<uint8_t*>(dex_file->Begin()) + offset) = '7';
41}
42
Andreas Gampee6215c02015-08-31 18:54:38 -070043static void FixUpChecksum(uint8_t* dex_file) {
44 DexFile::Header* header = reinterpret_cast<DexFile::Header*>(dex_file);
45 uint32_t expected_size = header->file_size_;
46 uint32_t adler_checksum = adler32(0L, Z_NULL, 0);
47 const uint32_t non_sum = sizeof(DexFile::Header::magic_) + sizeof(DexFile::Header::checksum_);
48 const uint8_t* non_sum_ptr = dex_file + non_sum;
49 adler_checksum = adler32(adler_checksum, non_sum_ptr, expected_size - non_sum);
50 header->checksum_ = adler_checksum;
51}
52
Andreas Gampee6215c02015-08-31 18:54:38 -070053class DexFileVerifierTest : public CommonRuntimeTest {
54 protected:
Aart Bik37d6a3b2016-06-21 18:30:10 -070055 DexFile* GetDexFile(const uint8_t* dex_bytes, size_t length) {
David Sehr733ddb22016-09-19 15:02:18 -070056 return new DexFile(dex_bytes, length, "tmp", 0, nullptr);
Aart Bik37d6a3b2016-06-21 18:30:10 -070057 }
58
Andreas Gampee6215c02015-08-31 18:54:38 -070059 void VerifyModification(const char* dex_file_base64_content,
60 const char* location,
61 std::function<void(DexFile*)> f,
62 const char* expected_error) {
Vladimir Marko59399ab2016-05-03 16:31:52 +010063 size_t length;
Alex Light9c20a142016-08-23 15:05:12 -070064 std::unique_ptr<uint8_t[]> dex_bytes(DecodeBase64(dex_file_base64_content, &length));
Vladimir Marko59399ab2016-05-03 16:31:52 +010065 CHECK(dex_bytes != nullptr);
66 // Note: `dex_file` will be destroyed before `dex_bytes`.
Aart Bik37d6a3b2016-06-21 18:30:10 -070067 std::unique_ptr<DexFile> dex_file(GetDexFile(dex_bytes.get(), length));
Andreas Gampee6215c02015-08-31 18:54:38 -070068 f(dex_file.get());
69 FixUpChecksum(const_cast<uint8_t*>(dex_file->Begin()));
70
Aart Bik37d6a3b2016-06-21 18:30:10 -070071 static constexpr bool kVerifyChecksum = true;
Andreas Gampee6215c02015-08-31 18:54:38 -070072 std::string error_msg;
73 bool success = DexFileVerifier::Verify(dex_file.get(),
74 dex_file->Begin(),
75 dex_file->Size(),
76 location,
Aart Bik37d6a3b2016-06-21 18:30:10 -070077 kVerifyChecksum,
Andreas Gampee6215c02015-08-31 18:54:38 -070078 &error_msg);
79 if (expected_error == nullptr) {
80 EXPECT_TRUE(success) << error_msg;
81 } else {
82 EXPECT_FALSE(success) << "Expected " << expected_error;
83 if (!success) {
84 EXPECT_NE(error_msg.find(expected_error), std::string::npos) << error_msg;
85 }
86 }
87 }
Andreas Gampee6215c02015-08-31 18:54:38 -070088};
89
Richard Uhlerfbef44d2014-12-23 09:48:51 -080090static std::unique_ptr<const DexFile> OpenDexFileBase64(const char* base64,
91 const char* location,
92 std::string* error_msg) {
Andreas Gampedf10b322014-06-11 21:46:05 -070093 // decode base64
Mathieu Chartier2cebb242015-04-21 16:50:40 -070094 CHECK(base64 != nullptr);
Andreas Gampedf10b322014-06-11 21:46:05 -070095 size_t length;
Ian Rogers13735952014-10-08 12:43:28 -070096 std::unique_ptr<uint8_t[]> dex_bytes(DecodeBase64(base64, &length));
Mathieu Chartier2cebb242015-04-21 16:50:40 -070097 CHECK(dex_bytes.get() != nullptr);
Andreas Gampedf10b322014-06-11 21:46:05 -070098
99 // write to provided file
100 std::unique_ptr<File> file(OS::CreateEmptyFile(location));
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700101 CHECK(file.get() != nullptr);
Andreas Gampedf10b322014-06-11 21:46:05 -0700102 if (!file->WriteFully(dex_bytes.get(), length)) {
103 PLOG(FATAL) << "Failed to write base64 as dex file";
104 }
Andreas Gampe4303ba92014-11-06 01:00:46 -0800105 if (file->FlushCloseOrErase() != 0) {
106 PLOG(FATAL) << "Could not flush and close test file.";
107 }
Andreas Gampedf10b322014-06-11 21:46:05 -0700108 file.reset();
109
110 // read dex file
111 ScopedObjectAccess soa(Thread::Current());
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800112 std::vector<std::unique_ptr<const DexFile>> tmp;
Aart Bik37d6a3b2016-06-21 18:30:10 -0700113 bool success = DexFile::Open(location, location, true, error_msg, &tmp);
Andreas Gampe833a4852014-05-21 18:46:59 -0700114 CHECK(success) << error_msg;
115 EXPECT_EQ(1U, tmp.size());
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800116 std::unique_ptr<const DexFile> dex_file = std::move(tmp[0]);
Andreas Gampe833a4852014-05-21 18:46:59 -0700117 EXPECT_EQ(PROT_READ, dex_file->GetPermissions());
118 EXPECT_TRUE(dex_file->IsReadOnly());
119 return dex_file;
Andreas Gampedf10b322014-06-11 21:46:05 -0700120}
121
Roland Levillain621b5ea2016-05-18 11:41:33 +0100122// To generate a base64 encoded Dex file (such as kGoodTestDex, below)
123// from Smali files, use:
124//
125// smali -o classes.dex class1.smali [class2.smali ...]
126// base64 classes.dex >classes.dex.base64
127
Andreas Gampedf10b322014-06-11 21:46:05 -0700128// For reference.
129static const char kGoodTestDex[] =
130 "ZGV4CjAzNQDrVbyVkxX1HljTznNf95AglkUAhQuFtmKkAgAAcAAAAHhWNBIAAAAAAAAAAAQCAAAN"
131 "AAAAcAAAAAYAAACkAAAAAgAAALwAAAABAAAA1AAAAAQAAADcAAAAAQAAAPwAAACIAQAAHAEAAFoB"
132 "AABiAQAAagEAAIEBAACVAQAAqQEAAL0BAADDAQAAzgEAANEBAADVAQAA2gEAAN8BAAABAAAAAgAA"
133 "AAMAAAAEAAAABQAAAAgAAAAIAAAABQAAAAAAAAAJAAAABQAAAFQBAAAEAAEACwAAAAAAAAAAAAAA"
134 "AAAAAAoAAAABAAEADAAAAAIAAAAAAAAAAAAAAAEAAAACAAAAAAAAAAcAAAAAAAAA8wEAAAAAAAAB"
135 "AAEAAQAAAOgBAAAEAAAAcBADAAAADgACAAAAAgAAAO0BAAAIAAAAYgAAABoBBgBuIAIAEAAOAAEA"
136 "AAADAAY8aW5pdD4ABkxUZXN0OwAVTGphdmEvaW8vUHJpbnRTdHJlYW07ABJMamF2YS9sYW5nL09i"
137 "amVjdDsAEkxqYXZhL2xhbmcvU3RyaW5nOwASTGphdmEvbGFuZy9TeXN0ZW07AARUZXN0AAlUZXN0"
138 "LmphdmEAAVYAAlZMAANmb28AA291dAAHcHJpbnRsbgABAAcOAAMABw54AAAAAgAAgYAEnAIBCbQC"
139 "AAAADQAAAAAAAAABAAAAAAAAAAEAAAANAAAAcAAAAAIAAAAGAAAApAAAAAMAAAACAAAAvAAAAAQA"
140 "AAABAAAA1AAAAAUAAAAEAAAA3AAAAAYAAAABAAAA/AAAAAEgAAACAAAAHAEAAAEQAAABAAAAVAEA"
141 "AAIgAAANAAAAWgEAAAMgAAACAAAA6AEAAAAgAAABAAAA8wEAAAAQAAABAAAABAIAAA==";
142
143TEST_F(DexFileVerifierTest, GoodDex) {
144 ScratchFile tmp;
145 std::string error_msg;
146 std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kGoodTestDex, tmp.GetFilename().c_str(),
147 &error_msg));
148 ASSERT_TRUE(raw.get() != nullptr) << error_msg;
149}
150
Andreas Gampedf10b322014-06-11 21:46:05 -0700151TEST_F(DexFileVerifierTest, MethodId) {
Andreas Gampee6215c02015-08-31 18:54:38 -0700152 // Class idx error.
153 VerifyModification(
154 kGoodTestDex,
155 "method_id_class_idx",
156 [](DexFile* dex_file) {
157 DexFile::MethodId* method_id = const_cast<DexFile::MethodId*>(&dex_file->GetMethodId(0));
158 method_id->class_idx_ = 0xFF;
159 },
160 "could not find declaring class for direct method index 0");
161
162 // Proto idx error.
163 VerifyModification(
164 kGoodTestDex,
165 "method_id_proto_idx",
166 [](DexFile* dex_file) {
167 DexFile::MethodId* method_id = const_cast<DexFile::MethodId*>(&dex_file->GetMethodId(0));
168 method_id->proto_idx_ = 0xFF;
169 },
170 "inter_method_id_item proto_idx");
171
172 // Name idx error.
173 VerifyModification(
174 kGoodTestDex,
175 "method_id_name_idx",
176 [](DexFile* dex_file) {
177 DexFile::MethodId* method_id = const_cast<DexFile::MethodId*>(&dex_file->GetMethodId(0));
178 method_id->name_idx_ = 0xFF;
179 },
180 "String index not available for method flags verification");
181}
182
183// Method flags test class generated from the following smali code. The declared-synchronized
184// flags are there to enforce a 3-byte uLEB128 encoding so we don't have to relayout
185// the code, but we need to remove them before doing tests.
186//
187// .class public LMethodFlags;
188// .super Ljava/lang/Object;
189//
190// .method public static constructor <clinit>()V
191// .registers 1
192// return-void
193// .end method
194//
195// .method public constructor <init>()V
196// .registers 1
197// return-void
198// .end method
199//
200// .method private declared-synchronized foo()V
201// .registers 1
202// return-void
203// .end method
204//
205// .method public declared-synchronized bar()V
206// .registers 1
207// return-void
208// .end method
209
210static const char kMethodFlagsTestDex[] =
211 "ZGV4CjAzNQCyOQrJaDBwiIWv5MIuYKXhxlLLsQcx5SwgAgAAcAAAAHhWNBIAAAAAAAAAAJgBAAAH"
212 "AAAAcAAAAAMAAACMAAAAAQAAAJgAAAAAAAAAAAAAAAQAAACkAAAAAQAAAMQAAAA8AQAA5AAAAOQA"
213 "AADuAAAA9gAAAAUBAAAZAQAAHAEAACEBAAACAAAAAwAAAAQAAAAEAAAAAgAAAAAAAAAAAAAAAAAA"
214 "AAAAAAABAAAAAAAAAAUAAAAAAAAABgAAAAAAAAABAAAAAQAAAAAAAAD/////AAAAAHoBAAAAAAAA"
215 "CDxjbGluaXQ+AAY8aW5pdD4ADUxNZXRob2RGbGFnczsAEkxqYXZhL2xhbmcvT2JqZWN0OwABVgAD"
216 "YmFyAANmb28AAAAAAAAAAQAAAAAAAAAAAAAAAQAAAA4AAAABAAEAAAAAAAAAAAABAAAADgAAAAEA"
217 "AQAAAAAAAAAAAAEAAAAOAAAAAQABAAAAAAAAAAAAAQAAAA4AAAADAQCJgASsAgGBgATAAgKCgAjU"
218 "AgKBgAjoAgAACwAAAAAAAAABAAAAAAAAAAEAAAAHAAAAcAAAAAIAAAADAAAAjAAAAAMAAAABAAAA"
219 "mAAAAAUAAAAEAAAApAAAAAYAAAABAAAAxAAAAAIgAAAHAAAA5AAAAAMQAAABAAAAKAEAAAEgAAAE"
220 "AAAALAEAAAAgAAABAAAAegEAAAAQAAABAAAAmAEAAA==";
221
222// Find the method data for the first method with the given name (from class 0). Note: the pointer
223// is to the access flags, so that the caller doesn't have to handle the leb128-encoded method-index
224// delta.
Vladimir Marko59399ab2016-05-03 16:31:52 +0100225static const uint8_t* FindMethodData(const DexFile* dex_file,
226 const char* name,
227 /*out*/ uint32_t* method_idx = nullptr) {
Andreas Gampee6215c02015-08-31 18:54:38 -0700228 const DexFile::ClassDef& class_def = dex_file->GetClassDef(0);
229 const uint8_t* class_data = dex_file->GetClassData(class_def);
230
231 ClassDataItemIterator it(*dex_file, class_data);
232
233 const uint8_t* trailing = class_data;
234 // Need to manually decode the four entries. DataPointer() doesn't work for this, as the first
235 // element has already been loaded into the iterator.
236 DecodeUnsignedLeb128(&trailing);
237 DecodeUnsignedLeb128(&trailing);
238 DecodeUnsignedLeb128(&trailing);
239 DecodeUnsignedLeb128(&trailing);
240
241 // Skip all fields.
242 while (it.HasNextStaticField() || it.HasNextInstanceField()) {
243 trailing = it.DataPointer();
244 it.Next();
Andreas Gampedf10b322014-06-11 21:46:05 -0700245 }
246
Andreas Gampee6215c02015-08-31 18:54:38 -0700247 while (it.HasNextDirectMethod() || it.HasNextVirtualMethod()) {
248 uint32_t method_index = it.GetMemberIndex();
249 uint32_t name_index = dex_file->GetMethodId(method_index).name_idx_;
250 const DexFile::StringId& string_id = dex_file->GetStringId(name_index);
251 const char* str = dex_file->GetStringData(string_id);
252 if (strcmp(name, str) == 0) {
Vladimir Marko59399ab2016-05-03 16:31:52 +0100253 if (method_idx != nullptr) {
254 *method_idx = method_index;
255 }
Andreas Gampee6215c02015-08-31 18:54:38 -0700256 DecodeUnsignedLeb128(&trailing);
257 return trailing;
258 }
259
260 trailing = it.DataPointer();
261 it.Next();
Andreas Gampedf10b322014-06-11 21:46:05 -0700262 }
263
Andreas Gampee6215c02015-08-31 18:54:38 -0700264 return nullptr;
265}
266
267// Set the method flags to the given value.
268static void SetMethodFlags(DexFile* dex_file, const char* method, uint32_t mask) {
269 uint8_t* method_flags_ptr = const_cast<uint8_t*>(FindMethodData(dex_file, method));
270 CHECK(method_flags_ptr != nullptr) << method;
271
272 // Unroll this, as we only have three bytes, anyways.
273 uint8_t base1 = static_cast<uint8_t>(mask & 0x7F);
274 *(method_flags_ptr++) = (base1 | 0x80);
275 mask >>= 7;
276
277 uint8_t base2 = static_cast<uint8_t>(mask & 0x7F);
278 *(method_flags_ptr++) = (base2 | 0x80);
279 mask >>= 7;
280
281 uint8_t base3 = static_cast<uint8_t>(mask & 0x7F);
282 *method_flags_ptr = base3;
283}
284
285static uint32_t GetMethodFlags(DexFile* dex_file, const char* method) {
286 const uint8_t* method_flags_ptr = const_cast<uint8_t*>(FindMethodData(dex_file, method));
287 CHECK(method_flags_ptr != nullptr) << method;
288 return DecodeUnsignedLeb128(&method_flags_ptr);
289}
290
291// Apply the given mask to method flags.
292static void ApplyMaskToMethodFlags(DexFile* dex_file, const char* method, uint32_t mask) {
293 uint32_t value = GetMethodFlags(dex_file, method);
294 value &= mask;
295 SetMethodFlags(dex_file, method, value);
296}
297
298// Apply the given mask to method flags.
299static void OrMaskToMethodFlags(DexFile* dex_file, const char* method, uint32_t mask) {
300 uint32_t value = GetMethodFlags(dex_file, method);
301 value |= mask;
302 SetMethodFlags(dex_file, method, value);
303}
304
305// Set code_off to 0 for the method.
306static void RemoveCode(DexFile* dex_file, const char* method) {
307 const uint8_t* ptr = FindMethodData(dex_file, method);
308 // Next is flags, pass.
309 DecodeUnsignedLeb128(&ptr);
310
311 // Figure out how many bytes the code_off is.
312 const uint8_t* tmp = ptr;
313 DecodeUnsignedLeb128(&tmp);
314 size_t bytes = tmp - ptr;
315
316 uint8_t* mod = const_cast<uint8_t*>(ptr);
317 for (size_t i = 1; i < bytes; ++i) {
318 *(mod++) = 0x80;
Andreas Gampedf10b322014-06-11 21:46:05 -0700319 }
Andreas Gampee6215c02015-08-31 18:54:38 -0700320 *mod = 0x00;
321}
322
323TEST_F(DexFileVerifierTest, MethodAccessFlagsBase) {
324 // Check that it's OK when the wrong declared-synchronized flag is removed from "foo."
325 VerifyModification(
326 kMethodFlagsTestDex,
327 "method_flags_ok",
328 [](DexFile* dex_file) {
329 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
330 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
331 },
332 nullptr);
333}
334
335TEST_F(DexFileVerifierTest, MethodAccessFlagsConstructors) {
336 // Make sure we still accept constructors without their flags.
337 VerifyModification(
338 kMethodFlagsTestDex,
339 "method_flags_missing_constructor_tag_ok",
340 [](DexFile* dex_file) {
341 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
342 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
343
344 ApplyMaskToMethodFlags(dex_file, "<init>", ~kAccConstructor);
345 ApplyMaskToMethodFlags(dex_file, "<clinit>", ~kAccConstructor);
346 },
347 nullptr);
348
349 constexpr const char* kConstructors[] = { "<clinit>", "<init>"};
350 for (size_t i = 0; i < 2; ++i) {
351 // Constructor with code marked native.
352 VerifyModification(
353 kMethodFlagsTestDex,
354 "method_flags_constructor_native",
355 [&](DexFile* dex_file) {
356 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
357 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
358
359 OrMaskToMethodFlags(dex_file, kConstructors[i], kAccNative);
360 },
361 "has code, but is marked native or abstract");
362 // Constructor with code marked abstract.
363 VerifyModification(
364 kMethodFlagsTestDex,
365 "method_flags_constructor_abstract",
366 [&](DexFile* dex_file) {
367 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
368 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
369
370 OrMaskToMethodFlags(dex_file, kConstructors[i], kAccAbstract);
371 },
372 "has code, but is marked native or abstract");
373 // Constructor as-is without code.
374 VerifyModification(
375 kMethodFlagsTestDex,
376 "method_flags_constructor_nocode",
377 [&](DexFile* dex_file) {
378 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
379 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
380
381 RemoveCode(dex_file, kConstructors[i]);
382 },
383 "has no code, but is not marked native or abstract");
384 // Constructor without code marked native.
385 VerifyModification(
386 kMethodFlagsTestDex,
387 "method_flags_constructor_native_nocode",
388 [&](DexFile* dex_file) {
Alex Light0ed05212016-05-06 17:36:36 -0700389 MakeDexVersion37(dex_file);
Andreas Gampee6215c02015-08-31 18:54:38 -0700390 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
391 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
392
393 OrMaskToMethodFlags(dex_file, kConstructors[i], kAccNative);
394 RemoveCode(dex_file, kConstructors[i]);
395 },
396 "must not be abstract or native");
397 // Constructor without code marked abstract.
398 VerifyModification(
399 kMethodFlagsTestDex,
400 "method_flags_constructor_abstract_nocode",
401 [&](DexFile* dex_file) {
Alex Light0ed05212016-05-06 17:36:36 -0700402 MakeDexVersion37(dex_file);
Andreas Gampee6215c02015-08-31 18:54:38 -0700403 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
404 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
405
406 OrMaskToMethodFlags(dex_file, kConstructors[i], kAccAbstract);
407 RemoveCode(dex_file, kConstructors[i]);
408 },
409 "must not be abstract or native");
410 }
411 // <init> may only have (modulo ignored):
412 // kAccPrivate | kAccProtected | kAccPublic | kAccStrict | kAccVarargs | kAccSynthetic
413 static constexpr uint32_t kInitAllowed[] = {
414 0,
415 kAccPrivate,
416 kAccProtected,
417 kAccPublic,
418 kAccStrict,
419 kAccVarargs,
420 kAccSynthetic
421 };
422 for (size_t i = 0; i < arraysize(kInitAllowed); ++i) {
423 VerifyModification(
424 kMethodFlagsTestDex,
425 "init_allowed_flags",
426 [&](DexFile* dex_file) {
427 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
428 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
429
430 ApplyMaskToMethodFlags(dex_file, "<init>", ~kAccPublic);
431 OrMaskToMethodFlags(dex_file, "<init>", kInitAllowed[i]);
432 },
433 nullptr);
434 }
435 // Only one of public-private-protected.
436 for (size_t i = 1; i < 8; ++i) {
437 if (POPCOUNT(i) < 2) {
438 continue;
439 }
440 // Technically the flags match, but just be defensive here.
441 uint32_t mask = ((i & 1) != 0 ? kAccPrivate : 0) |
442 ((i & 2) != 0 ? kAccProtected : 0) |
443 ((i & 4) != 0 ? kAccPublic : 0);
444 VerifyModification(
445 kMethodFlagsTestDex,
446 "init_one_of_ppp",
447 [&](DexFile* dex_file) {
448 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
449 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
450
451 ApplyMaskToMethodFlags(dex_file, "<init>", ~kAccPublic);
452 OrMaskToMethodFlags(dex_file, "<init>", mask);
453 },
454 "Method may have only one of public/protected/private");
455 }
456 // <init> doesn't allow
457 // kAccStatic | kAccFinal | kAccSynchronized | kAccBridge
458 // Need to handle static separately as it has its own error message.
459 VerifyModification(
460 kMethodFlagsTestDex,
461 "init_not_allowed_flags",
462 [&](DexFile* dex_file) {
Alex Light0ed05212016-05-06 17:36:36 -0700463 MakeDexVersion37(dex_file);
Andreas Gampee6215c02015-08-31 18:54:38 -0700464 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
465 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
466
467 ApplyMaskToMethodFlags(dex_file, "<init>", ~kAccPublic);
468 OrMaskToMethodFlags(dex_file, "<init>", kAccStatic);
469 },
Andreas Gampec9f0ba12016-02-09 09:21:04 -0800470 "Constructor 1(LMethodFlags;.<init>) is not flagged correctly wrt/ static");
Andreas Gampee6215c02015-08-31 18:54:38 -0700471 static constexpr uint32_t kInitNotAllowed[] = {
472 kAccFinal,
473 kAccSynchronized,
474 kAccBridge
475 };
476 for (size_t i = 0; i < arraysize(kInitNotAllowed); ++i) {
477 VerifyModification(
478 kMethodFlagsTestDex,
479 "init_not_allowed_flags",
480 [&](DexFile* dex_file) {
481 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
482 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
483
484 ApplyMaskToMethodFlags(dex_file, "<init>", ~kAccPublic);
485 OrMaskToMethodFlags(dex_file, "<init>", kInitNotAllowed[i]);
486 },
Andreas Gampec9f0ba12016-02-09 09:21:04 -0800487 "Constructor 1(LMethodFlags;.<init>) flagged inappropriately");
Andreas Gampee6215c02015-08-31 18:54:38 -0700488 }
489}
490
491TEST_F(DexFileVerifierTest, MethodAccessFlagsMethods) {
492 constexpr const char* kMethods[] = { "foo", "bar"};
493 for (size_t i = 0; i < arraysize(kMethods); ++i) {
494 // Make sure we reject non-constructors marked as constructors.
495 VerifyModification(
496 kMethodFlagsTestDex,
497 "method_flags_non_constructor",
498 [&](DexFile* dex_file) {
499 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
500 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
501
502 OrMaskToMethodFlags(dex_file, kMethods[i], kAccConstructor);
503 },
504 "is marked constructor, but doesn't match name");
505
506 VerifyModification(
507 kMethodFlagsTestDex,
508 "method_flags_native_with_code",
509 [&](DexFile* dex_file) {
510 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
511 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
512
513 OrMaskToMethodFlags(dex_file, kMethods[i], kAccNative);
514 },
515 "has code, but is marked native or abstract");
516
517 VerifyModification(
518 kMethodFlagsTestDex,
519 "method_flags_abstract_with_code",
520 [&](DexFile* dex_file) {
521 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
522 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
523
524 OrMaskToMethodFlags(dex_file, kMethods[i], kAccAbstract);
525 },
526 "has code, but is marked native or abstract");
527
528 VerifyModification(
529 kMethodFlagsTestDex,
530 "method_flags_non_abstract_native_no_code",
531 [&](DexFile* dex_file) {
532 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
533 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
534
535 RemoveCode(dex_file, kMethods[i]);
536 },
537 "has no code, but is not marked native or abstract");
538
539 // Abstract methods may not have the following flags.
540 constexpr uint32_t kAbstractDisallowed[] = {
541 kAccPrivate,
542 kAccStatic,
543 kAccFinal,
544 kAccNative,
545 kAccStrict,
546 kAccSynchronized,
547 };
548 for (size_t j = 0; j < arraysize(kAbstractDisallowed); ++j) {
549 VerifyModification(
550 kMethodFlagsTestDex,
551 "method_flags_abstract_and_disallowed_no_code",
552 [&](DexFile* dex_file) {
553 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
554 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
555
556 RemoveCode(dex_file, kMethods[i]);
557
558 // Can't check private and static with foo, as it's in the virtual list and gives a
559 // different error.
560 if (((GetMethodFlags(dex_file, kMethods[i]) & kAccPublic) != 0) &&
561 ((kAbstractDisallowed[j] & (kAccPrivate | kAccStatic)) != 0)) {
562 // Use another breaking flag.
563 OrMaskToMethodFlags(dex_file, kMethods[i], kAccAbstract | kAccFinal);
564 } else {
565 OrMaskToMethodFlags(dex_file, kMethods[i], kAccAbstract | kAbstractDisallowed[j]);
566 }
567 },
568 "has disallowed access flags");
569 }
570
571 // Only one of public-private-protected.
572 for (size_t j = 1; j < 8; ++j) {
573 if (POPCOUNT(j) < 2) {
574 continue;
575 }
576 // Technically the flags match, but just be defensive here.
577 uint32_t mask = ((j & 1) != 0 ? kAccPrivate : 0) |
578 ((j & 2) != 0 ? kAccProtected : 0) |
579 ((j & 4) != 0 ? kAccPublic : 0);
580 VerifyModification(
581 kMethodFlagsTestDex,
582 "method_flags_one_of_ppp",
583 [&](DexFile* dex_file) {
584 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
585 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
586
587 ApplyMaskToMethodFlags(dex_file, kMethods[i], ~kAccPublic);
588 OrMaskToMethodFlags(dex_file, kMethods[i], mask);
589 },
590 "Method may have only one of public/protected/private");
591 }
592 }
593}
594
595TEST_F(DexFileVerifierTest, MethodAccessFlagsIgnoredOK) {
596 constexpr const char* kMethods[] = { "<clinit>", "<init>", "foo", "bar"};
597 for (size_t i = 0; i < arraysize(kMethods); ++i) {
598 // All interesting method flags, other flags are to be ignored.
599 constexpr uint32_t kAllMethodFlags =
600 kAccPublic |
601 kAccPrivate |
602 kAccProtected |
603 kAccStatic |
604 kAccFinal |
605 kAccSynchronized |
606 kAccBridge |
607 kAccVarargs |
608 kAccNative |
609 kAccAbstract |
610 kAccStrict |
611 kAccSynthetic;
612 constexpr uint32_t kIgnoredMask = ~kAllMethodFlags & 0xFFFF;
613 VerifyModification(
614 kMethodFlagsTestDex,
615 "method_flags_ignored",
616 [&](DexFile* dex_file) {
617 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
618 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
619
620 OrMaskToMethodFlags(dex_file, kMethods[i], kIgnoredMask);
621 },
622 nullptr);
623 }
624}
625
Vladimir Marko59399ab2016-05-03 16:31:52 +0100626TEST_F(DexFileVerifierTest, B28552165) {
627 // Regression test for bad error string retrieval in different situations.
628 // Using invalid access flags to trigger the error.
629 VerifyModification(
630 kMethodFlagsTestDex,
631 "b28552165",
632 [](DexFile* dex_file) {
633 OrMaskToMethodFlags(dex_file, "foo", kAccPublic | kAccProtected);
634 uint32_t method_idx;
635 FindMethodData(dex_file, "foo", &method_idx);
636 auto* method_id = const_cast<DexFile::MethodId*>(&dex_file->GetMethodId(method_idx));
637 method_id->name_idx_ = dex_file->NumStringIds();
638 },
639 "Method may have only one of public/protected/private, LMethodFlags;.(error)");
640}
641
Andreas Gampee6215c02015-08-31 18:54:38 -0700642// Set of dex files for interface method tests. As it's not as easy to mutate method names, it's
643// just easier to break up bad cases.
644
Andreas Gampee6215c02015-08-31 18:54:38 -0700645// Standard interface. Use declared-synchronized again for 3B encoding.
646//
647// .class public interface LInterfaceMethodFlags;
648// .super Ljava/lang/Object;
649//
650// .method public static constructor <clinit>()V
651// .registers 1
652// return-void
653// .end method
654//
655// .method public abstract declared-synchronized foo()V
656// .end method
657static const char kMethodFlagsInterface[] =
658 "ZGV4CjAzNQCOM0odZ5bws1d9GSmumXaK5iE/7XxFpOm8AQAAcAAAAHhWNBIAAAAAAAAAADQBAAAF"
659 "AAAAcAAAAAMAAACEAAAAAQAAAJAAAAAAAAAAAAAAAAIAAACcAAAAAQAAAKwAAADwAAAAzAAAAMwA"
660 "AADWAAAA7gAAAAIBAAAFAQAAAQAAAAIAAAADAAAAAwAAAAIAAAAAAAAAAAAAAAAAAAAAAAAABAAA"
661 "AAAAAAABAgAAAQAAAAAAAAD/////AAAAACIBAAAAAAAACDxjbGluaXQ+ABZMSW50ZXJmYWNlTWV0"
662 "aG9kRmxhZ3M7ABJMamF2YS9sYW5nL09iamVjdDsAAVYAA2ZvbwAAAAAAAAABAAAAAAAAAAAAAAAB"
663 "AAAADgAAAAEBAImABJACAYGICAAAAAALAAAAAAAAAAEAAAAAAAAAAQAAAAUAAABwAAAAAgAAAAMA"
664 "AACEAAAAAwAAAAEAAACQAAAABQAAAAIAAACcAAAABgAAAAEAAACsAAAAAiAAAAUAAADMAAAAAxAA"
665 "AAEAAAAMAQAAASAAAAEAAAAQAQAAACAAAAEAAAAiAQAAABAAAAEAAAA0AQAA";
666
667// To simplify generation of interesting "sub-states" of src_value, allow a "simple" mask to apply
668// to a src_value, such that mask bit 0 applies to the lowest set bit in src_value, and so on.
669static uint32_t ApplyMaskShifted(uint32_t src_value, uint32_t mask) {
670 uint32_t result = 0;
671 uint32_t mask_index = 0;
672 while (src_value != 0) {
673 uint32_t index = CTZ(src_value);
674 if (((src_value & (1 << index)) != 0) &&
675 ((mask & (1 << mask_index)) != 0)) {
676 result |= (1 << index);
677 }
678 src_value &= ~(1 << index);
679 mask_index++;
680 }
681 return result;
682}
683
684TEST_F(DexFileVerifierTest, MethodAccessFlagsInterfaces) {
Andreas Gampee6215c02015-08-31 18:54:38 -0700685 VerifyModification(
686 kMethodFlagsInterface,
687 "method_flags_interface_ok",
688 [](DexFile* dex_file) {
689 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
690 },
691 nullptr);
Andreas Gampe76ed99d2016-03-28 18:31:29 -0700692 VerifyModification(
693 kMethodFlagsInterface,
694 "method_flags_interface_ok37",
695 [](DexFile* dex_file) {
696 MakeDexVersion37(dex_file);
697 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
698 },
699 nullptr);
Andreas Gampee6215c02015-08-31 18:54:38 -0700700
701 VerifyModification(
702 kMethodFlagsInterface,
703 "method_flags_interface_non_public",
704 [](DexFile* dex_file) {
705 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
706
707 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccPublic);
708 },
Andreas Gampe76ed99d2016-03-28 18:31:29 -0700709 nullptr); // Should be allowed in older dex versions for backwards compatibility.
710 VerifyModification(
711 kMethodFlagsInterface,
712 "method_flags_interface_non_public",
713 [](DexFile* dex_file) {
714 MakeDexVersion37(dex_file);
715 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
716
717 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccPublic);
718 },
Alex Lightd7c10c22016-03-31 10:03:07 -0700719 "Interface virtual method 1(LInterfaceMethodFlags;.foo) is not public");
Andreas Gampe76ed99d2016-03-28 18:31:29 -0700720
Andreas Gampee6215c02015-08-31 18:54:38 -0700721 VerifyModification(
722 kMethodFlagsInterface,
723 "method_flags_interface_non_abstract",
724 [](DexFile* dex_file) {
725 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
726
727 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccAbstract);
728 },
Andreas Gampec9f0ba12016-02-09 09:21:04 -0800729 "Method 1(LInterfaceMethodFlags;.foo) has no code, but is not marked native or abstract");
Andreas Gampee6215c02015-08-31 18:54:38 -0700730
731 VerifyModification(
732 kMethodFlagsInterface,
733 "method_flags_interface_static",
734 [](DexFile* dex_file) {
735 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
736
737 OrMaskToMethodFlags(dex_file, "foo", kAccStatic);
738 },
Andreas Gampec9f0ba12016-02-09 09:21:04 -0800739 "Direct/virtual method 1(LInterfaceMethodFlags;.foo) not in expected list 0");
Andreas Gampee6215c02015-08-31 18:54:38 -0700740 VerifyModification(
741 kMethodFlagsInterface,
742 "method_flags_interface_private",
743 [](DexFile* dex_file) {
744 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
745
746 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccPublic);
747 OrMaskToMethodFlags(dex_file, "foo", kAccPrivate);
748 },
Andreas Gampec9f0ba12016-02-09 09:21:04 -0800749 "Direct/virtual method 1(LInterfaceMethodFlags;.foo) not in expected list 0");
Andreas Gampee6215c02015-08-31 18:54:38 -0700750
751 VerifyModification(
752 kMethodFlagsInterface,
753 "method_flags_interface_non_public",
754 [](DexFile* dex_file) {
755 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
756
757 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccPublic);
758 },
Andreas Gampe76ed99d2016-03-28 18:31:29 -0700759 nullptr); // Should be allowed in older dex versions for backwards compatibility.
760 VerifyModification(
761 kMethodFlagsInterface,
762 "method_flags_interface_non_public",
763 [](DexFile* dex_file) {
764 MakeDexVersion37(dex_file);
765 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
766
767 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccPublic);
768 },
Alex Lightd7c10c22016-03-31 10:03:07 -0700769 "Interface virtual method 1(LInterfaceMethodFlags;.foo) is not public");
Andreas Gampe76ed99d2016-03-28 18:31:29 -0700770
Andreas Gampee6215c02015-08-31 18:54:38 -0700771 VerifyModification(
772 kMethodFlagsInterface,
773 "method_flags_interface_protected",
774 [](DexFile* dex_file) {
775 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
776
777 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccPublic);
778 OrMaskToMethodFlags(dex_file, "foo", kAccProtected);
779 },
Andreas Gampe76ed99d2016-03-28 18:31:29 -0700780 nullptr); // Should be allowed in older dex versions for backwards compatibility.
781 VerifyModification(
782 kMethodFlagsInterface,
783 "method_flags_interface_protected",
784 [](DexFile* dex_file) {
785 MakeDexVersion37(dex_file);
786 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
787
788 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccPublic);
789 OrMaskToMethodFlags(dex_file, "foo", kAccProtected);
790 },
Alex Lightd7c10c22016-03-31 10:03:07 -0700791 "Interface virtual method 1(LInterfaceMethodFlags;.foo) is not public");
Andreas Gampee6215c02015-08-31 18:54:38 -0700792
793 constexpr uint32_t kAllMethodFlags =
794 kAccPublic |
795 kAccPrivate |
796 kAccProtected |
797 kAccStatic |
798 kAccFinal |
799 kAccSynchronized |
800 kAccBridge |
801 kAccVarargs |
802 kAccNative |
803 kAccAbstract |
804 kAccStrict |
805 kAccSynthetic;
806 constexpr uint32_t kInterfaceMethodFlags =
807 kAccPublic | kAccAbstract | kAccVarargs | kAccBridge | kAccSynthetic;
808 constexpr uint32_t kInterfaceDisallowed = kAllMethodFlags &
809 ~kInterfaceMethodFlags &
810 // Already tested, needed to be separate.
811 ~kAccStatic &
812 ~kAccPrivate &
813 ~kAccProtected;
814 static_assert(kInterfaceDisallowed != 0, "There should be disallowed flags.");
815
816 uint32_t bits = POPCOUNT(kInterfaceDisallowed);
817 for (uint32_t i = 1; i < (1u << bits); ++i) {
818 VerifyModification(
819 kMethodFlagsInterface,
820 "method_flags_interface_non_abstract",
821 [&](DexFile* dex_file) {
822 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
823
824 uint32_t mask = ApplyMaskShifted(kInterfaceDisallowed, i);
825 if ((mask & kAccProtected) != 0) {
826 mask &= ~kAccProtected;
827 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccPublic);
828 }
829 OrMaskToMethodFlags(dex_file, "foo", mask);
830 },
Andreas Gampec9f0ba12016-02-09 09:21:04 -0800831 "Abstract method 1(LInterfaceMethodFlags;.foo) has disallowed access flags");
Andreas Gampee6215c02015-08-31 18:54:38 -0700832 }
833}
834
835///////////////////////////////////////////////////////////////////
836
837// Field flags.
838
839// Find the method data for the first method with the given name (from class 0). Note: the pointer
840// is to the access flags, so that the caller doesn't have to handle the leb128-encoded method-index
841// delta.
842static const uint8_t* FindFieldData(const DexFile* dex_file, const char* name) {
843 const DexFile::ClassDef& class_def = dex_file->GetClassDef(0);
844 const uint8_t* class_data = dex_file->GetClassData(class_def);
845
846 ClassDataItemIterator it(*dex_file, class_data);
847
848 const uint8_t* trailing = class_data;
849 // Need to manually decode the four entries. DataPointer() doesn't work for this, as the first
850 // element has already been loaded into the iterator.
851 DecodeUnsignedLeb128(&trailing);
852 DecodeUnsignedLeb128(&trailing);
853 DecodeUnsignedLeb128(&trailing);
854 DecodeUnsignedLeb128(&trailing);
855
856 while (it.HasNextStaticField() || it.HasNextInstanceField()) {
857 uint32_t field_index = it.GetMemberIndex();
858 uint32_t name_index = dex_file->GetFieldId(field_index).name_idx_;
859 const DexFile::StringId& string_id = dex_file->GetStringId(name_index);
860 const char* str = dex_file->GetStringData(string_id);
861 if (strcmp(name, str) == 0) {
862 DecodeUnsignedLeb128(&trailing);
863 return trailing;
864 }
865
866 trailing = it.DataPointer();
867 it.Next();
868 }
869
870 return nullptr;
871}
872
873// Set the method flags to the given value.
874static void SetFieldFlags(DexFile* dex_file, const char* field, uint32_t mask) {
875 uint8_t* field_flags_ptr = const_cast<uint8_t*>(FindFieldData(dex_file, field));
876 CHECK(field_flags_ptr != nullptr) << field;
877
878 // Unroll this, as we only have three bytes, anyways.
879 uint8_t base1 = static_cast<uint8_t>(mask & 0x7F);
880 *(field_flags_ptr++) = (base1 | 0x80);
881 mask >>= 7;
882
883 uint8_t base2 = static_cast<uint8_t>(mask & 0x7F);
884 *(field_flags_ptr++) = (base2 | 0x80);
885 mask >>= 7;
886
887 uint8_t base3 = static_cast<uint8_t>(mask & 0x7F);
888 *field_flags_ptr = base3;
889}
890
891static uint32_t GetFieldFlags(DexFile* dex_file, const char* field) {
892 const uint8_t* field_flags_ptr = const_cast<uint8_t*>(FindFieldData(dex_file, field));
893 CHECK(field_flags_ptr != nullptr) << field;
894 return DecodeUnsignedLeb128(&field_flags_ptr);
895}
896
897// Apply the given mask to method flags.
898static void ApplyMaskToFieldFlags(DexFile* dex_file, const char* field, uint32_t mask) {
899 uint32_t value = GetFieldFlags(dex_file, field);
900 value &= mask;
901 SetFieldFlags(dex_file, field, value);
902}
903
904// Apply the given mask to method flags.
905static void OrMaskToFieldFlags(DexFile* dex_file, const char* field, uint32_t mask) {
906 uint32_t value = GetFieldFlags(dex_file, field);
907 value |= mask;
908 SetFieldFlags(dex_file, field, value);
909}
910
911// Standard class. Use declared-synchronized again for 3B encoding.
912//
913// .class public LFieldFlags;
914// .super Ljava/lang/Object;
915//
916// .field declared-synchronized public foo:I
917//
918// .field declared-synchronized public static bar:I
919
920static const char kFieldFlagsTestDex[] =
921 "ZGV4CjAzNQBtLw7hydbfv4TdXidZyzAB70W7w3vnYJRwAQAAcAAAAHhWNBIAAAAAAAAAAAABAAAF"
922 "AAAAcAAAAAMAAACEAAAAAAAAAAAAAAACAAAAkAAAAAAAAAAAAAAAAQAAAKAAAACwAAAAwAAAAMAA"
923 "AADDAAAA0QAAAOUAAADqAAAAAAAAAAEAAAACAAAAAQAAAAMAAAABAAAABAAAAAEAAAABAAAAAgAA"
924 "AAAAAAD/////AAAAAPQAAAAAAAAAAUkADExGaWVsZEZsYWdzOwASTGphdmEvbGFuZy9PYmplY3Q7"
925 "AANiYXIAA2ZvbwAAAAAAAAEBAAAAiYAIAYGACAkAAAAAAAAAAQAAAAAAAAABAAAABQAAAHAAAAAC"
926 "AAAAAwAAAIQAAAAEAAAAAgAAAJAAAAAGAAAAAQAAAKAAAAACIAAABQAAAMAAAAADEAAAAQAAAPAA"
927 "AAAAIAAAAQAAAPQAAAAAEAAAAQAAAAABAAA=";
928
929TEST_F(DexFileVerifierTest, FieldAccessFlagsBase) {
930 // Check that it's OK when the wrong declared-synchronized flag is removed from "foo."
931 VerifyModification(
932 kFieldFlagsTestDex,
933 "field_flags_ok",
934 [](DexFile* dex_file) {
935 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
936 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
937 },
938 nullptr);
939}
940
941TEST_F(DexFileVerifierTest, FieldAccessFlagsWrongList) {
942 // Mark the field so that it should appear in the opposite list (instance vs static).
943 VerifyModification(
944 kFieldFlagsTestDex,
945 "field_flags_wrong_list",
946 [](DexFile* dex_file) {
947 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
948 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
949
950 OrMaskToFieldFlags(dex_file, "foo", kAccStatic);
951 },
952 "Static/instance field not in expected list");
953 VerifyModification(
954 kFieldFlagsTestDex,
955 "field_flags_wrong_list",
956 [](DexFile* dex_file) {
957 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
958 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
959
960 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccStatic);
961 },
962 "Static/instance field not in expected list");
963}
964
965TEST_F(DexFileVerifierTest, FieldAccessFlagsPPP) {
966 static const char* kFields[] = { "foo", "bar" };
967 for (size_t i = 0; i < arraysize(kFields); ++i) {
968 // Should be OK to remove public.
969 VerifyModification(
970 kFieldFlagsTestDex,
971 "field_flags_non_public",
972 [&](DexFile* dex_file) {
973 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
974 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
975
976 ApplyMaskToFieldFlags(dex_file, kFields[i], ~kAccPublic);
977 },
978 nullptr);
979 constexpr uint32_t kAccFlags = kAccPublic | kAccPrivate | kAccProtected;
980 uint32_t bits = POPCOUNT(kAccFlags);
981 for (uint32_t j = 1; j < (1u << bits); ++j) {
982 if (POPCOUNT(j) < 2) {
983 continue;
984 }
985 VerifyModification(
986 kFieldFlagsTestDex,
987 "field_flags_ppp",
988 [&](DexFile* dex_file) {
989 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
990 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
991
992 ApplyMaskToFieldFlags(dex_file, kFields[i], ~kAccPublic);
993 uint32_t mask = ApplyMaskShifted(kAccFlags, j);
994 OrMaskToFieldFlags(dex_file, kFields[i], mask);
995 },
996 "Field may have only one of public/protected/private");
997 }
998 }
999}
1000
1001TEST_F(DexFileVerifierTest, FieldAccessFlagsIgnoredOK) {
1002 constexpr const char* kFields[] = { "foo", "bar"};
1003 for (size_t i = 0; i < arraysize(kFields); ++i) {
1004 // All interesting method flags, other flags are to be ignored.
1005 constexpr uint32_t kAllFieldFlags =
1006 kAccPublic |
1007 kAccPrivate |
1008 kAccProtected |
1009 kAccStatic |
1010 kAccFinal |
1011 kAccVolatile |
1012 kAccTransient |
1013 kAccSynthetic |
1014 kAccEnum;
1015 constexpr uint32_t kIgnoredMask = ~kAllFieldFlags & 0xFFFF;
1016 VerifyModification(
1017 kFieldFlagsTestDex,
1018 "field_flags_ignored",
1019 [&](DexFile* dex_file) {
1020 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1021 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
1022
1023 OrMaskToFieldFlags(dex_file, kFields[i], kIgnoredMask);
1024 },
1025 nullptr);
1026 }
1027}
1028
1029TEST_F(DexFileVerifierTest, FieldAccessFlagsVolatileFinal) {
1030 constexpr const char* kFields[] = { "foo", "bar"};
1031 for (size_t i = 0; i < arraysize(kFields); ++i) {
1032 VerifyModification(
1033 kFieldFlagsTestDex,
1034 "field_flags_final_and_volatile",
1035 [&](DexFile* dex_file) {
1036 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1037 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
1038
1039 OrMaskToFieldFlags(dex_file, kFields[i], kAccVolatile | kAccFinal);
1040 },
1041 "Fields may not be volatile and final");
1042 }
1043}
1044
1045// Standard interface. Needs to be separate from class as interfaces do not allow instance fields.
1046// Use declared-synchronized again for 3B encoding.
1047//
1048// .class public interface LInterfaceFieldFlags;
1049// .super Ljava/lang/Object;
1050//
1051// .field declared-synchronized public static final foo:I
1052
1053static const char kFieldFlagsInterfaceTestDex[] =
1054 "ZGV4CjAzNQCVMHfEimR1zZPk6hl6O9GPAYqkl3u0umFkAQAAcAAAAHhWNBIAAAAAAAAAAPQAAAAE"
1055 "AAAAcAAAAAMAAACAAAAAAAAAAAAAAAABAAAAjAAAAAAAAAAAAAAAAQAAAJQAAACwAAAAtAAAALQA"
1056 "AAC3AAAAzgAAAOIAAAAAAAAAAQAAAAIAAAABAAAAAwAAAAEAAAABAgAAAgAAAAAAAAD/////AAAA"
1057 "AOwAAAAAAAAAAUkAFUxJbnRlcmZhY2VGaWVsZEZsYWdzOwASTGphdmEvbGFuZy9PYmplY3Q7AANm"
1058 "b28AAAAAAAABAAAAAJmACAkAAAAAAAAAAQAAAAAAAAABAAAABAAAAHAAAAACAAAAAwAAAIAAAAAE"
1059 "AAAAAQAAAIwAAAAGAAAAAQAAAJQAAAACIAAABAAAALQAAAADEAAAAQAAAOgAAAAAIAAAAQAAAOwA"
1060 "AAAAEAAAAQAAAPQAAAA=";
1061
1062TEST_F(DexFileVerifierTest, FieldAccessFlagsInterface) {
1063 VerifyModification(
1064 kFieldFlagsInterfaceTestDex,
1065 "field_flags_interface",
1066 [](DexFile* dex_file) {
1067 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1068 },
1069 nullptr);
Andreas Gampe76ed99d2016-03-28 18:31:29 -07001070 VerifyModification(
1071 kFieldFlagsInterfaceTestDex,
1072 "field_flags_interface",
1073 [](DexFile* dex_file) {
1074 MakeDexVersion37(dex_file);
1075 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1076 },
1077 nullptr);
Andreas Gampee6215c02015-08-31 18:54:38 -07001078
1079 VerifyModification(
1080 kFieldFlagsInterfaceTestDex,
1081 "field_flags_interface_non_public",
1082 [](DexFile* dex_file) {
1083 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1084
1085 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccPublic);
1086 },
Andreas Gampe76ed99d2016-03-28 18:31:29 -07001087 nullptr); // Should be allowed in older dex versions for backwards compatibility.
1088 VerifyModification(
1089 kFieldFlagsInterfaceTestDex,
1090 "field_flags_interface_non_public",
1091 [](DexFile* dex_file) {
1092 MakeDexVersion37(dex_file);
1093 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1094
1095 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccPublic);
1096 },
Andreas Gampee6215c02015-08-31 18:54:38 -07001097 "Interface field is not public final static");
Andreas Gampe76ed99d2016-03-28 18:31:29 -07001098
Andreas Gampee6215c02015-08-31 18:54:38 -07001099 VerifyModification(
1100 kFieldFlagsInterfaceTestDex,
1101 "field_flags_interface_non_final",
1102 [](DexFile* dex_file) {
1103 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1104
1105 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccFinal);
1106 },
Andreas Gampe76ed99d2016-03-28 18:31:29 -07001107 nullptr); // Should be allowed in older dex versions for backwards compatibility.
1108 VerifyModification(
1109 kFieldFlagsInterfaceTestDex,
1110 "field_flags_interface_non_final",
1111 [](DexFile* dex_file) {
1112 MakeDexVersion37(dex_file);
1113 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1114
1115 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccFinal);
1116 },
Andreas Gampee6215c02015-08-31 18:54:38 -07001117 "Interface field is not public final static");
Andreas Gampe76ed99d2016-03-28 18:31:29 -07001118
Andreas Gampee6215c02015-08-31 18:54:38 -07001119 VerifyModification(
1120 kFieldFlagsInterfaceTestDex,
1121 "field_flags_interface_protected",
1122 [](DexFile* dex_file) {
1123 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1124
1125 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccPublic);
1126 OrMaskToFieldFlags(dex_file, "foo", kAccProtected);
1127 },
Andreas Gampe76ed99d2016-03-28 18:31:29 -07001128 nullptr); // Should be allowed in older dex versions for backwards compatibility.
1129 VerifyModification(
1130 kFieldFlagsInterfaceTestDex,
1131 "field_flags_interface_protected",
1132 [](DexFile* dex_file) {
1133 MakeDexVersion37(dex_file);
1134 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1135
1136 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccPublic);
1137 OrMaskToFieldFlags(dex_file, "foo", kAccProtected);
1138 },
Andreas Gampee6215c02015-08-31 18:54:38 -07001139 "Interface field is not public final static");
Andreas Gampe76ed99d2016-03-28 18:31:29 -07001140
Andreas Gampee6215c02015-08-31 18:54:38 -07001141 VerifyModification(
1142 kFieldFlagsInterfaceTestDex,
1143 "field_flags_interface_private",
1144 [](DexFile* dex_file) {
1145 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1146
1147 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccPublic);
1148 OrMaskToFieldFlags(dex_file, "foo", kAccPrivate);
1149 },
Andreas Gampe76ed99d2016-03-28 18:31:29 -07001150 nullptr); // Should be allowed in older dex versions for backwards compatibility.
1151 VerifyModification(
1152 kFieldFlagsInterfaceTestDex,
1153 "field_flags_interface_private",
1154 [](DexFile* dex_file) {
1155 MakeDexVersion37(dex_file);
1156 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1157
1158 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccPublic);
1159 OrMaskToFieldFlags(dex_file, "foo", kAccPrivate);
1160 },
Andreas Gampee6215c02015-08-31 18:54:38 -07001161 "Interface field is not public final static");
1162
1163 VerifyModification(
1164 kFieldFlagsInterfaceTestDex,
1165 "field_flags_interface_synthetic",
1166 [](DexFile* dex_file) {
1167 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1168
1169 OrMaskToFieldFlags(dex_file, "foo", kAccSynthetic);
1170 },
1171 nullptr);
1172
1173 constexpr uint32_t kAllFieldFlags =
1174 kAccPublic |
1175 kAccPrivate |
1176 kAccProtected |
1177 kAccStatic |
1178 kAccFinal |
1179 kAccVolatile |
1180 kAccTransient |
1181 kAccSynthetic |
1182 kAccEnum;
1183 constexpr uint32_t kInterfaceFieldFlags = kAccPublic | kAccStatic | kAccFinal | kAccSynthetic;
1184 constexpr uint32_t kInterfaceDisallowed = kAllFieldFlags &
1185 ~kInterfaceFieldFlags &
1186 ~kAccProtected &
1187 ~kAccPrivate;
1188 static_assert(kInterfaceDisallowed != 0, "There should be disallowed flags.");
1189
1190 uint32_t bits = POPCOUNT(kInterfaceDisallowed);
1191 for (uint32_t i = 1; i < (1u << bits); ++i) {
1192 VerifyModification(
1193 kFieldFlagsInterfaceTestDex,
1194 "field_flags_interface_disallowed",
1195 [&](DexFile* dex_file) {
1196 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1197
1198 uint32_t mask = ApplyMaskShifted(kInterfaceDisallowed, i);
1199 if ((mask & kAccProtected) != 0) {
1200 mask &= ~kAccProtected;
1201 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccPublic);
1202 }
1203 OrMaskToFieldFlags(dex_file, "foo", mask);
1204 },
Andreas Gampe76ed99d2016-03-28 18:31:29 -07001205 nullptr); // Should be allowed in older dex versions for backwards compatibility.
1206 VerifyModification(
1207 kFieldFlagsInterfaceTestDex,
1208 "field_flags_interface_disallowed",
1209 [&](DexFile* dex_file) {
1210 MakeDexVersion37(dex_file);
1211 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1212
1213 uint32_t mask = ApplyMaskShifted(kInterfaceDisallowed, i);
1214 if ((mask & kAccProtected) != 0) {
1215 mask &= ~kAccProtected;
1216 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccPublic);
1217 }
1218 OrMaskToFieldFlags(dex_file, "foo", mask);
1219 },
Andreas Gampee6215c02015-08-31 18:54:38 -07001220 "Interface field has disallowed flag");
1221 }
1222}
1223
1224// Standard bad interface. Needs to be separate from class as interfaces do not allow instance
1225// fields. Use declared-synchronized again for 3B encoding.
1226//
1227// .class public interface LInterfaceFieldFlags;
1228// .super Ljava/lang/Object;
1229//
1230// .field declared-synchronized public final foo:I
1231
1232static const char kFieldFlagsInterfaceBadTestDex[] =
1233 "ZGV4CjAzNQByMUnqYKHBkUpvvNp+9CnZ2VyDkKnRN6VkAQAAcAAAAHhWNBIAAAAAAAAAAPQAAAAE"
1234 "AAAAcAAAAAMAAACAAAAAAAAAAAAAAAABAAAAjAAAAAAAAAAAAAAAAQAAAJQAAACwAAAAtAAAALQA"
1235 "AAC3AAAAzgAAAOIAAAAAAAAAAQAAAAIAAAABAAAAAwAAAAEAAAABAgAAAgAAAAAAAAD/////AAAA"
1236 "AOwAAAAAAAAAAUkAFUxJbnRlcmZhY2VGaWVsZEZsYWdzOwASTGphdmEvbGFuZy9PYmplY3Q7AANm"
1237 "b28AAAAAAAAAAQAAAJGACAkAAAAAAAAAAQAAAAAAAAABAAAABAAAAHAAAAACAAAAAwAAAIAAAAAE"
1238 "AAAAAQAAAIwAAAAGAAAAAQAAAJQAAAACIAAABAAAALQAAAADEAAAAQAAAOgAAAAAIAAAAQAAAOwA"
1239 "AAAAEAAAAQAAAPQAAAA=";
1240
1241TEST_F(DexFileVerifierTest, FieldAccessFlagsInterfaceNonStatic) {
1242 VerifyModification(
1243 kFieldFlagsInterfaceBadTestDex,
1244 "field_flags_interface_non_static",
1245 [](DexFile* dex_file) {
1246 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1247 },
Andreas Gampe76ed99d2016-03-28 18:31:29 -07001248 nullptr); // Should be allowed in older dex versions for backwards compatibility.
1249 VerifyModification(
1250 kFieldFlagsInterfaceBadTestDex,
1251 "field_flags_interface_non_static",
1252 [](DexFile* dex_file) {
1253 MakeDexVersion37(dex_file);
1254 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1255 },
Andreas Gampee6215c02015-08-31 18:54:38 -07001256 "Interface field is not public final static");
Andreas Gampedf10b322014-06-11 21:46:05 -07001257}
1258
Logan Chiendd3208d2015-04-19 23:27:52 +08001259// Generated from:
1260//
1261// .class public LTest;
1262// .super Ljava/lang/Object;
1263// .source "Test.java"
1264//
1265// .method public constructor <init>()V
1266// .registers 1
1267//
1268// .prologue
1269// .line 1
1270// invoke-direct {p0}, Ljava/lang/Object;-><init>()V
1271//
1272// return-void
1273// .end method
1274//
1275// .method public static main()V
1276// .registers 2
1277//
1278// const-string v0, "a"
1279// const-string v0, "b"
1280// const-string v0, "c"
1281// const-string v0, "d"
1282// const-string v0, "e"
1283// const-string v0, "f"
1284// const-string v0, "g"
1285// const-string v0, "h"
1286// const-string v0, "i"
1287// const-string v0, "j"
1288// const-string v0, "k"
1289//
1290// .local v1, "local_var":Ljava/lang/String;
1291// const-string v1, "test"
1292// .end method
1293
1294static const char kDebugInfoTestDex[] =
1295 "ZGV4CjAzNQCHRkHix2eIMQgvLD/0VGrlllZLo0Rb6VyUAgAAcAAAAHhWNBIAAAAAAAAAAAwCAAAU"
1296 "AAAAcAAAAAQAAADAAAAAAQAAANAAAAAAAAAAAAAAAAMAAADcAAAAAQAAAPQAAACAAQAAFAEAABQB"
1297 "AAAcAQAAJAEAADgBAABMAQAAVwEAAFoBAABdAQAAYAEAAGMBAABmAQAAaQEAAGwBAABvAQAAcgEA"
1298 "AHUBAAB4AQAAewEAAIYBAACMAQAAAQAAAAIAAAADAAAABQAAAAUAAAADAAAAAAAAAAAAAAAAAAAA"
1299 "AAAAABIAAAABAAAAAAAAAAAAAAABAAAAAQAAAAAAAAAEAAAAAAAAAPwBAAAAAAAABjxpbml0PgAG"
1300 "TFRlc3Q7ABJMamF2YS9sYW5nL09iamVjdDsAEkxqYXZhL2xhbmcvU3RyaW5nOwAJVGVzdC5qYXZh"
1301 "AAFWAAFhAAFiAAFjAAFkAAFlAAFmAAFnAAFoAAFpAAFqAAFrAAlsb2NhbF92YXIABG1haW4ABHRl"
1302 "c3QAAAABAAcOAAAAARYDARIDAAAAAQABAAEAAACUAQAABAAAAHAQAgAAAA4AAgAAAAAAAACZAQAA"
1303 "GAAAABoABgAaAAcAGgAIABoACQAaAAoAGgALABoADAAaAA0AGgAOABoADwAaABAAGgETAAAAAgAA"
1304 "gYAEpAMBCbwDAAALAAAAAAAAAAEAAAAAAAAAAQAAABQAAABwAAAAAgAAAAQAAADAAAAAAwAAAAEA"
1305 "AADQAAAABQAAAAMAAADcAAAABgAAAAEAAAD0AAAAAiAAABQAAAAUAQAAAyAAAAIAAACUAQAAASAA"
1306 "AAIAAACkAQAAACAAAAEAAAD8AQAAABAAAAEAAAAMAgAA";
1307
1308TEST_F(DexFileVerifierTest, DebugInfoTypeIdxTest) {
1309 {
1310 // The input dex file should be good before modification.
1311 ScratchFile tmp;
1312 std::string error_msg;
1313 std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kDebugInfoTestDex,
1314 tmp.GetFilename().c_str(),
1315 &error_msg));
1316 ASSERT_TRUE(raw.get() != nullptr) << error_msg;
1317 }
1318
Andreas Gampee6215c02015-08-31 18:54:38 -07001319 // Modify the debug information entry.
1320 VerifyModification(
1321 kDebugInfoTestDex,
1322 "debug_start_type_idx",
1323 [](DexFile* dex_file) {
1324 *(const_cast<uint8_t*>(dex_file->Begin()) + 416) = 0x14U;
1325 },
1326 "DBG_START_LOCAL type_idx");
Logan Chiendd3208d2015-04-19 23:27:52 +08001327}
1328
Andreas Gampeb512c0e2016-02-19 19:45:34 -08001329TEST_F(DexFileVerifierTest, SectionAlignment) {
1330 {
1331 // The input dex file should be good before modification. Any file is fine, as long as it
1332 // uses all sections.
1333 ScratchFile tmp;
1334 std::string error_msg;
1335 std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kGoodTestDex,
1336 tmp.GetFilename().c_str(),
1337 &error_msg));
1338 ASSERT_TRUE(raw.get() != nullptr) << error_msg;
1339 }
1340
1341 // Modify all section offsets to be unaligned.
1342 constexpr size_t kSections = 7;
1343 for (size_t i = 0; i < kSections; ++i) {
1344 VerifyModification(
1345 kGoodTestDex,
1346 "section_align",
1347 [&](DexFile* dex_file) {
1348 DexFile::Header* header = const_cast<DexFile::Header*>(
1349 reinterpret_cast<const DexFile::Header*>(dex_file->Begin()));
1350 uint32_t* off_ptr;
1351 switch (i) {
1352 case 0:
1353 off_ptr = &header->map_off_;
1354 break;
1355 case 1:
1356 off_ptr = &header->string_ids_off_;
1357 break;
1358 case 2:
1359 off_ptr = &header->type_ids_off_;
1360 break;
1361 case 3:
1362 off_ptr = &header->proto_ids_off_;
1363 break;
1364 case 4:
1365 off_ptr = &header->field_ids_off_;
1366 break;
1367 case 5:
1368 off_ptr = &header->method_ids_off_;
1369 break;
1370 case 6:
1371 off_ptr = &header->class_defs_off_;
1372 break;
1373
1374 static_assert(kSections == 7, "kSections is wrong");
1375 default:
1376 LOG(FATAL) << "Unexpected section";
1377 UNREACHABLE();
1378 }
1379 ASSERT_TRUE(off_ptr != nullptr);
1380 ASSERT_NE(*off_ptr, 0U) << i; // Should already contain a value (in use).
1381 (*off_ptr)++; // Add one, which should misalign it (all the sections
1382 // above are aligned by 4).
1383 },
1384 "should be aligned by 4 for");
1385 }
1386}
1387
Vladimir Marko0ca8add2016-05-03 17:17:50 +01001388// Generated from
1389//
1390// .class LOverloading;
1391//
1392// .super Ljava/lang/Object;
1393//
1394// .method public static foo()V
1395// .registers 1
1396// return-void
1397// .end method
1398//
1399// .method public static foo(I)V
1400// .registers 1
1401// return-void
1402// .end method
1403static const char kProtoOrderingTestDex[] =
1404 "ZGV4CjAzNQA1L+ABE6voQ9Lr4Ci//efB53oGnDr5PinsAQAAcAAAAHhWNBIAAAAAAAAAAFgBAAAG"
1405 "AAAAcAAAAAQAAACIAAAAAgAAAJgAAAAAAAAAAAAAAAIAAACwAAAAAQAAAMAAAAAMAQAA4AAAAOAA"
1406 "AADjAAAA8gAAAAYBAAAJAQAADQEAAAAAAAABAAAAAgAAAAMAAAADAAAAAwAAAAAAAAAEAAAAAwAA"
1407 "ABQBAAABAAAABQAAAAEAAQAFAAAAAQAAAAAAAAACAAAAAAAAAP////8AAAAASgEAAAAAAAABSQAN"
1408 "TE92ZXJsb2FkaW5nOwASTGphdmEvbGFuZy9PYmplY3Q7AAFWAAJWSQADZm9vAAAAAQAAAAAAAAAA"
1409 "AAAAAAAAAAEAAAAAAAAAAAAAAAEAAAAOAAAAAQABAAAAAAAAAAAAAQAAAA4AAAACAAAJpAIBCbgC"
1410 "AAAMAAAAAAAAAAEAAAAAAAAAAQAAAAYAAABwAAAAAgAAAAQAAACIAAAAAwAAAAIAAACYAAAABQAA"
1411 "AAIAAACwAAAABgAAAAEAAADAAAAAAiAAAAYAAADgAAAAARAAAAEAAAAUAQAAAxAAAAIAAAAcAQAA"
1412 "ASAAAAIAAAAkAQAAACAAAAEAAABKAQAAABAAAAEAAABYAQAA";
1413
1414TEST_F(DexFileVerifierTest, ProtoOrdering) {
1415 {
1416 // The input dex file should be good before modification.
1417 ScratchFile tmp;
1418 std::string error_msg;
1419 std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kProtoOrderingTestDex,
1420 tmp.GetFilename().c_str(),
1421 &error_msg));
1422 ASSERT_TRUE(raw.get() != nullptr) << error_msg;
1423 }
1424
1425 // Modify the order of the ProtoIds for two overloads of "foo" with the
1426 // same return type and one having longer parameter list than the other.
1427 for (size_t i = 0; i != 2; ++i) {
1428 VerifyModification(
1429 kProtoOrderingTestDex,
1430 "proto_ordering",
1431 [i](DexFile* dex_file) {
1432 uint32_t method_idx;
1433 const uint8_t* data = FindMethodData(dex_file, "foo", &method_idx);
1434 CHECK(data != nullptr);
1435 // There should be 2 methods called "foo".
1436 CHECK_LT(method_idx + 1u, dex_file->NumMethodIds());
1437 CHECK_EQ(dex_file->GetMethodId(method_idx).name_idx_,
1438 dex_file->GetMethodId(method_idx + 1).name_idx_);
1439 CHECK_EQ(dex_file->GetMethodId(method_idx).proto_idx_ + 1u,
1440 dex_file->GetMethodId(method_idx + 1).proto_idx_);
1441 // Their return types should be the same.
1442 uint32_t proto1_idx = dex_file->GetMethodId(method_idx).proto_idx_;
1443 const DexFile::ProtoId& proto1 = dex_file->GetProtoId(proto1_idx);
1444 const DexFile::ProtoId& proto2 = dex_file->GetProtoId(proto1_idx + 1u);
1445 CHECK_EQ(proto1.return_type_idx_, proto2.return_type_idx_);
1446 // And the first should not have any parameters while the second should have some.
1447 CHECK(!DexFileParameterIterator(*dex_file, proto1).HasNext());
1448 CHECK(DexFileParameterIterator(*dex_file, proto2).HasNext());
1449 if (i == 0) {
1450 // Swap the proto parameters and shorties to break the ordering.
1451 std::swap(const_cast<uint32_t&>(proto1.parameters_off_),
1452 const_cast<uint32_t&>(proto2.parameters_off_));
1453 std::swap(const_cast<uint32_t&>(proto1.shorty_idx_),
1454 const_cast<uint32_t&>(proto2.shorty_idx_));
1455 } else {
1456 // Copy the proto parameters and shorty to create duplicate proto id.
1457 const_cast<uint32_t&>(proto1.parameters_off_) = proto2.parameters_off_;
1458 const_cast<uint32_t&>(proto1.shorty_idx_) = proto2.shorty_idx_;
1459 }
1460 },
1461 "Out-of-order proto_id arguments");
1462 }
1463}
1464
Roland Levillain621b5ea2016-05-18 11:41:33 +01001465// To generate a base64 encoded Dex file version 037 from Smali files, use:
1466//
1467// smali --api-level 24 -o classes.dex class1.smali [class2.smali ...]
1468// base64 classes.dex >classes.dex.base64
1469
1470// Dex file version 037 generated from:
1471//
1472// .class public LB28685551;
1473// .super LB28685551;
1474
1475static const char kClassExtendsItselfTestDex[] =
1476 "ZGV4CjAzNwDeGbgRg1kb6swszpcTWrrOAALB++F4OPT0AAAAcAAAAHhWNBIAAAAAAAAAAKgAAAAB"
1477 "AAAAcAAAAAEAAAB0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAHgAAABcAAAAmAAAAJgA"
1478 "AAAAAAAAAAAAAAEAAAAAAAAAAAAAAP////8AAAAAAAAAAAAAAAALTEIyODY4NTU1MTsAAAAABgAA"
1479 "AAAAAAABAAAAAAAAAAEAAAABAAAAcAAAAAIAAAABAAAAdAAAAAYAAAABAAAAeAAAAAIgAAABAAAA"
1480 "mAAAAAAQAAABAAAAqAAAAA==";
1481
1482TEST_F(DexFileVerifierTest, ClassExtendsItself) {
1483 VerifyModification(
1484 kClassExtendsItselfTestDex,
1485 "class_extends_itself",
1486 [](DexFile* dex_file ATTRIBUTE_UNUSED) { /* empty */ },
1487 "Class with same type idx as its superclass: '0'");
1488}
1489
1490// Dex file version 037 generated from:
1491//
1492// .class public LFoo;
1493// .super LBar;
1494//
1495// and:
1496//
1497// .class public LBar;
1498// .super LFoo;
1499
1500static const char kClassesExtendOneAnotherTestDex[] =
1501 "ZGV4CjAzNwBXHSrwpDMwRBkg+L+JeQCuFNRLhQ86duEcAQAAcAAAAHhWNBIAAAAAAAAAANAAAAAC"
1502 "AAAAcAAAAAIAAAB4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAIAAAABcAAAAwAAAAMAA"
1503 "AADHAAAAAAAAAAEAAAABAAAAAQAAAAAAAAAAAAAA/////wAAAAAAAAAAAAAAAAAAAAABAAAAAQAA"
1504 "AAAAAAD/////AAAAAAAAAAAAAAAABUxCYXI7AAVMRm9vOwAAAAYAAAAAAAAAAQAAAAAAAAABAAAA"
1505 "AgAAAHAAAAACAAAAAgAAAHgAAAAGAAAAAgAAAIAAAAACIAAAAgAAAMAAAAAAEAAAAQAAANAAAAA=";
1506
1507TEST_F(DexFileVerifierTest, ClassesExtendOneAnother) {
1508 VerifyModification(
1509 kClassesExtendOneAnotherTestDex,
1510 "classes_extend_one_another",
1511 [](DexFile* dex_file ATTRIBUTE_UNUSED) { /* empty */ },
1512 "Invalid class definition ordering: class with type idx: '1' defined before"
1513 " superclass with type idx: '0'");
1514}
1515
1516// Dex file version 037 generated from:
1517//
1518// .class public LAll;
1519// .super LYour;
1520//
1521// and:
1522//
1523// .class public LYour;
1524// .super LBase;
1525//
1526// and:
1527//
1528// .class public LBase;
1529// .super LAll;
1530
1531static const char kCircularClassInheritanceTestDex[] =
1532 "ZGV4CjAzNwBMJxgP0SJz6oLXnKfl+J7lSEORLRwF5LNMAQAAcAAAAHhWNBIAAAAAAAAAAAABAAAD"
1533 "AAAAcAAAAAMAAAB8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAIgAAABkAAAA6AAAAOgA"
1534 "AADvAAAA9wAAAAAAAAABAAAAAgAAAAEAAAABAAAAAAAAAAAAAAD/////AAAAAAAAAAAAAAAAAgAA"
1535 "AAEAAAABAAAAAAAAAP////8AAAAAAAAAAAAAAAAAAAAAAQAAAAIAAAAAAAAA/////wAAAAAAAAAA"
1536 "AAAAAAVMQWxsOwAGTEJhc2U7AAZMWW91cjsAAAYAAAAAAAAAAQAAAAAAAAABAAAAAwAAAHAAAAAC"
1537 "AAAAAwAAAHwAAAAGAAAAAwAAAIgAAAACIAAAAwAAAOgAAAAAEAAAAQAAAAABAAA=";
1538
1539TEST_F(DexFileVerifierTest, CircularClassInheritance) {
1540 VerifyModification(
1541 kCircularClassInheritanceTestDex,
1542 "circular_class_inheritance",
1543 [](DexFile* dex_file ATTRIBUTE_UNUSED) { /* empty */ },
1544 "Invalid class definition ordering: class with type idx: '1' defined before"
1545 " superclass with type idx: '0'");
1546}
1547
1548// Dex file version 037 generated from:
1549//
1550// .class public abstract interface LInterfaceImplementsItself;
1551// .super Ljava/lang/Object;
1552// .implements LInterfaceImplementsItself;
1553
1554static const char kInterfaceImplementsItselfTestDex[] =
1555 "ZGV4CjAzNwCKKrjatp8XbXl5S/bEVJnqaBhjZkQY4440AQAAcAAAAHhWNBIAAAAAAAAAANwAAAAC"
1556 "AAAAcAAAAAIAAAB4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAIAAAACUAAAAoAAAAKAA"
1557 "AAC9AAAAAAAAAAEAAAAAAAAAAQYAAAEAAADUAAAA/////wAAAAAAAAAAAAAAABtMSW50ZXJmYWNl"
1558 "SW1wbGVtZW50c0l0c2VsZjsAEkxqYXZhL2xhbmcvT2JqZWN0OwAAAAABAAAAAAAAAAcAAAAAAAAA"
1559 "AQAAAAAAAAABAAAAAgAAAHAAAAACAAAAAgAAAHgAAAAGAAAAAQAAAIAAAAACIAAAAgAAAKAAAAAB"
1560 "EAAAAQAAANQAAAAAEAAAAQAAANwAAAA=";
1561
1562TEST_F(DexFileVerifierTest, InterfaceImplementsItself) {
1563 VerifyModification(
1564 kInterfaceImplementsItselfTestDex,
1565 "interface_implements_itself",
1566 [](DexFile* dex_file ATTRIBUTE_UNUSED) { /* empty */ },
1567 "Class with same type idx as implemented interface: '0'");
1568}
1569
1570// Dex file version 037 generated from:
1571//
1572// .class public abstract interface LPing;
1573// .super Ljava/lang/Object;
1574// .implements LPong;
1575//
1576// and:
1577//
1578// .class public abstract interface LPong;
1579// .super Ljava/lang/Object;
1580// .implements LPing;
1581
1582static const char kInterfacesImplementOneAnotherTestDex[] =
1583 "ZGV4CjAzNwD0Kk9sxlYdg3Dy1Cff0gQCuJAQfEP6ohZUAQAAcAAAAHhWNBIAAAAAAAAAAPwAAAAD"
1584 "AAAAcAAAAAMAAAB8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAIgAAACMAAAAyAAAAMgA"
1585 "AADQAAAA2AAAAAAAAAABAAAAAgAAAAEAAAABBgAAAgAAAOwAAAD/////AAAAAAAAAAAAAAAAAAAA"
1586 "AAEGAAACAAAA9AAAAP////8AAAAAAAAAAAAAAAAGTFBpbmc7AAZMUG9uZzsAEkxqYXZhL2xhbmcv"
1587 "T2JqZWN0OwABAAAAAAAAAAEAAAABAAAABwAAAAAAAAABAAAAAAAAAAEAAAADAAAAcAAAAAIAAAAD"
1588 "AAAAfAAAAAYAAAACAAAAiAAAAAIgAAADAAAAyAAAAAEQAAACAAAA7AAAAAAQAAABAAAA/AAAAA==";
1589
1590TEST_F(DexFileVerifierTest, InterfacesImplementOneAnother) {
1591 VerifyModification(
1592 kInterfacesImplementOneAnotherTestDex,
1593 "interfaces_implement_one_another",
1594 [](DexFile* dex_file ATTRIBUTE_UNUSED) { /* empty */ },
1595 "Invalid class definition ordering: class with type idx: '1' defined before"
1596 " implemented interface with type idx: '0'");
1597}
1598
1599// Dex file version 037 generated from:
1600//
1601// .class public abstract interface LA;
1602// .super Ljava/lang/Object;
1603// .implements LB;
1604//
1605// and:
1606//
1607// .class public abstract interface LB;
1608// .super Ljava/lang/Object;
1609// .implements LC;
1610//
1611// and:
1612//
1613// .class public abstract interface LC;
1614// .super Ljava/lang/Object;
1615// .implements LA;
1616
1617static const char kCircularInterfaceImplementationTestDex[] =
1618 "ZGV4CjAzNwCzKmD5Fol6XAU6ichYHcUTIP7Z7MdTcEmEAQAAcAAAAHhWNBIAAAAAAAAAACwBAAAE"
1619 "AAAAcAAAAAQAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAJAAAACUAAAA8AAAAPAA"
1620 "AAD1AAAA+gAAAP8AAAAAAAAAAQAAAAIAAAADAAAAAgAAAAEGAAADAAAAHAEAAP////8AAAAAAAAA"
1621 "AAAAAAABAAAAAQYAAAMAAAAUAQAA/////wAAAAAAAAAAAAAAAAAAAAABBgAAAwAAACQBAAD/////"
1622 "AAAAAAAAAAAAAAAAA0xBOwADTEI7AANMQzsAEkxqYXZhL2xhbmcvT2JqZWN0OwAAAQAAAAIAAAAB"
1623 "AAAAAAAAAAEAAAABAAAABwAAAAAAAAABAAAAAAAAAAEAAAAEAAAAcAAAAAIAAAAEAAAAgAAAAAYA"
1624 "AAADAAAAkAAAAAIgAAAEAAAA8AAAAAEQAAADAAAAFAEAAAAQAAABAAAALAEAAA==";
1625
1626TEST_F(DexFileVerifierTest, CircularInterfaceImplementation) {
1627 VerifyModification(
1628 kCircularInterfaceImplementationTestDex,
1629 "circular_interface_implementation",
1630 [](DexFile* dex_file ATTRIBUTE_UNUSED) { /* empty */ },
1631 "Invalid class definition ordering: class with type idx: '2' defined before"
1632 " implemented interface with type idx: '0'");
1633}
1634
Aart Bik37d6a3b2016-06-21 18:30:10 -07001635TEST_F(DexFileVerifierTest, Checksum) {
1636 size_t length;
Alex Light9c20a142016-08-23 15:05:12 -07001637 std::unique_ptr<uint8_t[]> dex_bytes(DecodeBase64(kGoodTestDex, &length));
Aart Bik37d6a3b2016-06-21 18:30:10 -07001638 CHECK(dex_bytes != nullptr);
1639 // Note: `dex_file` will be destroyed before `dex_bytes`.
1640 std::unique_ptr<DexFile> dex_file(GetDexFile(dex_bytes.get(), length));
1641 std::string error_msg;
1642
1643 // Good checksum: all pass.
1644 EXPECT_TRUE(DexFileVerifier::Verify(dex_file.get(),
1645 dex_file->Begin(),
1646 dex_file->Size(),
1647 "good checksum, no verify",
1648 /*verify_checksum*/ false,
1649 &error_msg));
1650 EXPECT_TRUE(DexFileVerifier::Verify(dex_file.get(),
1651 dex_file->Begin(),
1652 dex_file->Size(),
1653 "good checksum, verify",
1654 /*verify_checksum*/ true,
1655 &error_msg));
1656
1657 // Bad checksum: !verify_checksum passes verify_checksum fails.
1658 DexFile::Header* header = reinterpret_cast<DexFile::Header*>(
1659 const_cast<uint8_t*>(dex_file->Begin()));
1660 header->checksum_ = 0;
1661 EXPECT_TRUE(DexFileVerifier::Verify(dex_file.get(),
1662 dex_file->Begin(),
1663 dex_file->Size(),
1664 "bad checksum, no verify",
1665 /*verify_checksum*/ false,
1666 &error_msg));
1667 EXPECT_FALSE(DexFileVerifier::Verify(dex_file.get(),
1668 dex_file->Begin(),
1669 dex_file->Size(),
1670 "bad checksum, verify",
1671 /*verify_checksum*/ true,
1672 &error_msg));
1673 EXPECT_NE(error_msg.find("Bad checksum"), std::string::npos) << error_msg;
1674}
1675
Andreas Gampedf10b322014-06-11 21:46:05 -07001676} // namespace art