blob: 721f26c0b8b2e98459e005f9be88a09f06b568fd [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"
Ian Rogerse63db272014-07-15 15:36:11 -070030#include "scoped_thread_state_change.h"
31#include "thread-inl.h"
Andreas Gampedf10b322014-06-11 21:46:05 -070032
33namespace art {
34
Ian Rogers13735952014-10-08 12:43:28 -070035static const uint8_t kBase64Map[256] = {
Andreas Gampedf10b322014-06-11 21:46:05 -070036 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
37 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
38 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
39 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
40 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
41 255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6,
42 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, // NOLINT
43 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, // NOLINT
44 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
45 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, // NOLINT
46 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, // NOLINT
47 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
48 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
49 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
50 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
51 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
52 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
53 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
54 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
55 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
56 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
57 255, 255, 255, 255
58};
59
Vladimir Marko59399ab2016-05-03 16:31:52 +010060static inline std::unique_ptr<uint8_t[]> DecodeBase64(const char* src, size_t* dst_size) {
Ian Rogers13735952014-10-08 12:43:28 -070061 std::vector<uint8_t> tmp;
Andreas Gampedf10b322014-06-11 21:46:05 -070062 uint32_t t = 0, y = 0;
63 int g = 3;
64 for (size_t i = 0; src[i] != '\0'; ++i) {
Ian Rogers13735952014-10-08 12:43:28 -070065 uint8_t c = kBase64Map[src[i] & 0xFF];
Andreas Gampedf10b322014-06-11 21:46:05 -070066 if (c == 255) continue;
67 // the final = symbols are read and used to trim the remaining bytes
68 if (c == 254) {
69 c = 0;
70 // prevent g < 0 which would potentially allow an overflow later
71 if (--g < 0) {
72 *dst_size = 0;
73 return nullptr;
74 }
75 } else if (g != 3) {
76 // we only allow = to be at the end
77 *dst_size = 0;
78 return nullptr;
79 }
80 t = (t << 6) | c;
81 if (++y == 4) {
82 tmp.push_back((t >> 16) & 255);
83 if (g > 1) {
84 tmp.push_back((t >> 8) & 255);
85 }
86 if (g > 2) {
87 tmp.push_back(t & 255);
88 }
89 y = t = 0;
90 }
91 }
92 if (y != 0) {
93 *dst_size = 0;
94 return nullptr;
95 }
Ian Rogers13735952014-10-08 12:43:28 -070096 std::unique_ptr<uint8_t[]> dst(new uint8_t[tmp.size()]);
Andreas Gampedf10b322014-06-11 21:46:05 -070097 if (dst_size != nullptr) {
98 *dst_size = tmp.size();
99 } else {
100 *dst_size = 0;
101 }
102 std::copy(tmp.begin(), tmp.end(), dst.get());
Vladimir Marko59399ab2016-05-03 16:31:52 +0100103 return dst;
Andreas Gampedf10b322014-06-11 21:46:05 -0700104}
105
Andreas Gampee6215c02015-08-31 18:54:38 -0700106static void FixUpChecksum(uint8_t* dex_file) {
107 DexFile::Header* header = reinterpret_cast<DexFile::Header*>(dex_file);
108 uint32_t expected_size = header->file_size_;
109 uint32_t adler_checksum = adler32(0L, Z_NULL, 0);
110 const uint32_t non_sum = sizeof(DexFile::Header::magic_) + sizeof(DexFile::Header::checksum_);
111 const uint8_t* non_sum_ptr = dex_file + non_sum;
112 adler_checksum = adler32(adler_checksum, non_sum_ptr, expected_size - non_sum);
113 header->checksum_ = adler_checksum;
114}
115
Andreas Gampee6215c02015-08-31 18:54:38 -0700116class DexFileVerifierTest : public CommonRuntimeTest {
117 protected:
118 void VerifyModification(const char* dex_file_base64_content,
119 const char* location,
120 std::function<void(DexFile*)> f,
121 const char* expected_error) {
Vladimir Marko59399ab2016-05-03 16:31:52 +0100122 size_t length;
123 std::unique_ptr<uint8_t[]> dex_bytes = DecodeBase64(dex_file_base64_content, &length);
124 CHECK(dex_bytes != nullptr);
125 // Note: `dex_file` will be destroyed before `dex_bytes`.
126 std::unique_ptr<DexFile> dex_file(
127 new DexFile(dex_bytes.get(), length, "tmp", 0, nullptr, nullptr));
Andreas Gampee6215c02015-08-31 18:54:38 -0700128 f(dex_file.get());
129 FixUpChecksum(const_cast<uint8_t*>(dex_file->Begin()));
130
131 std::string error_msg;
132 bool success = DexFileVerifier::Verify(dex_file.get(),
133 dex_file->Begin(),
134 dex_file->Size(),
135 location,
136 &error_msg);
137 if (expected_error == nullptr) {
138 EXPECT_TRUE(success) << error_msg;
139 } else {
140 EXPECT_FALSE(success) << "Expected " << expected_error;
141 if (!success) {
142 EXPECT_NE(error_msg.find(expected_error), std::string::npos) << error_msg;
143 }
144 }
145 }
Andreas Gampee6215c02015-08-31 18:54:38 -0700146};
147
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800148static std::unique_ptr<const DexFile> OpenDexFileBase64(const char* base64,
149 const char* location,
150 std::string* error_msg) {
Andreas Gampedf10b322014-06-11 21:46:05 -0700151 // decode base64
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700152 CHECK(base64 != nullptr);
Andreas Gampedf10b322014-06-11 21:46:05 -0700153 size_t length;
Ian Rogers13735952014-10-08 12:43:28 -0700154 std::unique_ptr<uint8_t[]> dex_bytes(DecodeBase64(base64, &length));
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700155 CHECK(dex_bytes.get() != nullptr);
Andreas Gampedf10b322014-06-11 21:46:05 -0700156
157 // write to provided file
158 std::unique_ptr<File> file(OS::CreateEmptyFile(location));
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700159 CHECK(file.get() != nullptr);
Andreas Gampedf10b322014-06-11 21:46:05 -0700160 if (!file->WriteFully(dex_bytes.get(), length)) {
161 PLOG(FATAL) << "Failed to write base64 as dex file";
162 }
Andreas Gampe4303ba92014-11-06 01:00:46 -0800163 if (file->FlushCloseOrErase() != 0) {
164 PLOG(FATAL) << "Could not flush and close test file.";
165 }
Andreas Gampedf10b322014-06-11 21:46:05 -0700166 file.reset();
167
168 // read dex file
169 ScopedObjectAccess soa(Thread::Current());
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800170 std::vector<std::unique_ptr<const DexFile>> tmp;
Andreas Gampe833a4852014-05-21 18:46:59 -0700171 bool success = DexFile::Open(location, location, error_msg, &tmp);
172 CHECK(success) << error_msg;
173 EXPECT_EQ(1U, tmp.size());
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800174 std::unique_ptr<const DexFile> dex_file = std::move(tmp[0]);
Andreas Gampe833a4852014-05-21 18:46:59 -0700175 EXPECT_EQ(PROT_READ, dex_file->GetPermissions());
176 EXPECT_TRUE(dex_file->IsReadOnly());
177 return dex_file;
Andreas Gampedf10b322014-06-11 21:46:05 -0700178}
179
Andreas Gampedf10b322014-06-11 21:46:05 -0700180// For reference.
181static const char kGoodTestDex[] =
182 "ZGV4CjAzNQDrVbyVkxX1HljTznNf95AglkUAhQuFtmKkAgAAcAAAAHhWNBIAAAAAAAAAAAQCAAAN"
183 "AAAAcAAAAAYAAACkAAAAAgAAALwAAAABAAAA1AAAAAQAAADcAAAAAQAAAPwAAACIAQAAHAEAAFoB"
184 "AABiAQAAagEAAIEBAACVAQAAqQEAAL0BAADDAQAAzgEAANEBAADVAQAA2gEAAN8BAAABAAAAAgAA"
185 "AAMAAAAEAAAABQAAAAgAAAAIAAAABQAAAAAAAAAJAAAABQAAAFQBAAAEAAEACwAAAAAAAAAAAAAA"
186 "AAAAAAoAAAABAAEADAAAAAIAAAAAAAAAAAAAAAEAAAACAAAAAAAAAAcAAAAAAAAA8wEAAAAAAAAB"
187 "AAEAAQAAAOgBAAAEAAAAcBADAAAADgACAAAAAgAAAO0BAAAIAAAAYgAAABoBBgBuIAIAEAAOAAEA"
188 "AAADAAY8aW5pdD4ABkxUZXN0OwAVTGphdmEvaW8vUHJpbnRTdHJlYW07ABJMamF2YS9sYW5nL09i"
189 "amVjdDsAEkxqYXZhL2xhbmcvU3RyaW5nOwASTGphdmEvbGFuZy9TeXN0ZW07AARUZXN0AAlUZXN0"
190 "LmphdmEAAVYAAlZMAANmb28AA291dAAHcHJpbnRsbgABAAcOAAMABw54AAAAAgAAgYAEnAIBCbQC"
191 "AAAADQAAAAAAAAABAAAAAAAAAAEAAAANAAAAcAAAAAIAAAAGAAAApAAAAAMAAAACAAAAvAAAAAQA"
192 "AAABAAAA1AAAAAUAAAAEAAAA3AAAAAYAAAABAAAA/AAAAAEgAAACAAAAHAEAAAEQAAABAAAAVAEA"
193 "AAIgAAANAAAAWgEAAAMgAAACAAAA6AEAAAAgAAABAAAA8wEAAAAQAAABAAAABAIAAA==";
194
195TEST_F(DexFileVerifierTest, GoodDex) {
196 ScratchFile tmp;
197 std::string error_msg;
198 std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kGoodTestDex, tmp.GetFilename().c_str(),
199 &error_msg));
200 ASSERT_TRUE(raw.get() != nullptr) << error_msg;
201}
202
Andreas Gampedf10b322014-06-11 21:46:05 -0700203TEST_F(DexFileVerifierTest, MethodId) {
Andreas Gampee6215c02015-08-31 18:54:38 -0700204 // Class idx error.
205 VerifyModification(
206 kGoodTestDex,
207 "method_id_class_idx",
208 [](DexFile* dex_file) {
209 DexFile::MethodId* method_id = const_cast<DexFile::MethodId*>(&dex_file->GetMethodId(0));
210 method_id->class_idx_ = 0xFF;
211 },
212 "could not find declaring class for direct method index 0");
213
214 // Proto idx error.
215 VerifyModification(
216 kGoodTestDex,
217 "method_id_proto_idx",
218 [](DexFile* dex_file) {
219 DexFile::MethodId* method_id = const_cast<DexFile::MethodId*>(&dex_file->GetMethodId(0));
220 method_id->proto_idx_ = 0xFF;
221 },
222 "inter_method_id_item proto_idx");
223
224 // Name idx error.
225 VerifyModification(
226 kGoodTestDex,
227 "method_id_name_idx",
228 [](DexFile* dex_file) {
229 DexFile::MethodId* method_id = const_cast<DexFile::MethodId*>(&dex_file->GetMethodId(0));
230 method_id->name_idx_ = 0xFF;
231 },
232 "String index not available for method flags verification");
233}
234
235// Method flags test class generated from the following smali code. The declared-synchronized
236// flags are there to enforce a 3-byte uLEB128 encoding so we don't have to relayout
237// the code, but we need to remove them before doing tests.
238//
239// .class public LMethodFlags;
240// .super Ljava/lang/Object;
241//
242// .method public static constructor <clinit>()V
243// .registers 1
244// return-void
245// .end method
246//
247// .method public constructor <init>()V
248// .registers 1
249// return-void
250// .end method
251//
252// .method private declared-synchronized foo()V
253// .registers 1
254// return-void
255// .end method
256//
257// .method public declared-synchronized bar()V
258// .registers 1
259// return-void
260// .end method
261
262static const char kMethodFlagsTestDex[] =
263 "ZGV4CjAzNQCyOQrJaDBwiIWv5MIuYKXhxlLLsQcx5SwgAgAAcAAAAHhWNBIAAAAAAAAAAJgBAAAH"
264 "AAAAcAAAAAMAAACMAAAAAQAAAJgAAAAAAAAAAAAAAAQAAACkAAAAAQAAAMQAAAA8AQAA5AAAAOQA"
265 "AADuAAAA9gAAAAUBAAAZAQAAHAEAACEBAAACAAAAAwAAAAQAAAAEAAAAAgAAAAAAAAAAAAAAAAAA"
266 "AAAAAAABAAAAAAAAAAUAAAAAAAAABgAAAAAAAAABAAAAAQAAAAAAAAD/////AAAAAHoBAAAAAAAA"
267 "CDxjbGluaXQ+AAY8aW5pdD4ADUxNZXRob2RGbGFnczsAEkxqYXZhL2xhbmcvT2JqZWN0OwABVgAD"
268 "YmFyAANmb28AAAAAAAAAAQAAAAAAAAAAAAAAAQAAAA4AAAABAAEAAAAAAAAAAAABAAAADgAAAAEA"
269 "AQAAAAAAAAAAAAEAAAAOAAAAAQABAAAAAAAAAAAAAQAAAA4AAAADAQCJgASsAgGBgATAAgKCgAjU"
270 "AgKBgAjoAgAACwAAAAAAAAABAAAAAAAAAAEAAAAHAAAAcAAAAAIAAAADAAAAjAAAAAMAAAABAAAA"
271 "mAAAAAUAAAAEAAAApAAAAAYAAAABAAAAxAAAAAIgAAAHAAAA5AAAAAMQAAABAAAAKAEAAAEgAAAE"
272 "AAAALAEAAAAgAAABAAAAegEAAAAQAAABAAAAmAEAAA==";
273
274// Find the method data for the first method with the given name (from class 0). Note: the pointer
275// is to the access flags, so that the caller doesn't have to handle the leb128-encoded method-index
276// delta.
Vladimir Marko59399ab2016-05-03 16:31:52 +0100277static const uint8_t* FindMethodData(const DexFile* dex_file,
278 const char* name,
279 /*out*/ uint32_t* method_idx = nullptr) {
Andreas Gampee6215c02015-08-31 18:54:38 -0700280 const DexFile::ClassDef& class_def = dex_file->GetClassDef(0);
281 const uint8_t* class_data = dex_file->GetClassData(class_def);
282
283 ClassDataItemIterator it(*dex_file, class_data);
284
285 const uint8_t* trailing = class_data;
286 // Need to manually decode the four entries. DataPointer() doesn't work for this, as the first
287 // element has already been loaded into the iterator.
288 DecodeUnsignedLeb128(&trailing);
289 DecodeUnsignedLeb128(&trailing);
290 DecodeUnsignedLeb128(&trailing);
291 DecodeUnsignedLeb128(&trailing);
292
293 // Skip all fields.
294 while (it.HasNextStaticField() || it.HasNextInstanceField()) {
295 trailing = it.DataPointer();
296 it.Next();
Andreas Gampedf10b322014-06-11 21:46:05 -0700297 }
298
Andreas Gampee6215c02015-08-31 18:54:38 -0700299 while (it.HasNextDirectMethod() || it.HasNextVirtualMethod()) {
300 uint32_t method_index = it.GetMemberIndex();
301 uint32_t name_index = dex_file->GetMethodId(method_index).name_idx_;
302 const DexFile::StringId& string_id = dex_file->GetStringId(name_index);
303 const char* str = dex_file->GetStringData(string_id);
304 if (strcmp(name, str) == 0) {
Vladimir Marko59399ab2016-05-03 16:31:52 +0100305 if (method_idx != nullptr) {
306 *method_idx = method_index;
307 }
Andreas Gampee6215c02015-08-31 18:54:38 -0700308 DecodeUnsignedLeb128(&trailing);
309 return trailing;
310 }
311
312 trailing = it.DataPointer();
313 it.Next();
Andreas Gampedf10b322014-06-11 21:46:05 -0700314 }
315
Andreas Gampee6215c02015-08-31 18:54:38 -0700316 return nullptr;
317}
318
319// Set the method flags to the given value.
320static void SetMethodFlags(DexFile* dex_file, const char* method, uint32_t mask) {
321 uint8_t* method_flags_ptr = const_cast<uint8_t*>(FindMethodData(dex_file, method));
322 CHECK(method_flags_ptr != nullptr) << method;
323
324 // Unroll this, as we only have three bytes, anyways.
325 uint8_t base1 = static_cast<uint8_t>(mask & 0x7F);
326 *(method_flags_ptr++) = (base1 | 0x80);
327 mask >>= 7;
328
329 uint8_t base2 = static_cast<uint8_t>(mask & 0x7F);
330 *(method_flags_ptr++) = (base2 | 0x80);
331 mask >>= 7;
332
333 uint8_t base3 = static_cast<uint8_t>(mask & 0x7F);
334 *method_flags_ptr = base3;
335}
336
337static uint32_t GetMethodFlags(DexFile* dex_file, const char* method) {
338 const uint8_t* method_flags_ptr = const_cast<uint8_t*>(FindMethodData(dex_file, method));
339 CHECK(method_flags_ptr != nullptr) << method;
340 return DecodeUnsignedLeb128(&method_flags_ptr);
341}
342
343// Apply the given mask to method flags.
344static void ApplyMaskToMethodFlags(DexFile* dex_file, const char* method, uint32_t mask) {
345 uint32_t value = GetMethodFlags(dex_file, method);
346 value &= mask;
347 SetMethodFlags(dex_file, method, value);
348}
349
350// Apply the given mask to method flags.
351static void OrMaskToMethodFlags(DexFile* dex_file, const char* method, uint32_t mask) {
352 uint32_t value = GetMethodFlags(dex_file, method);
353 value |= mask;
354 SetMethodFlags(dex_file, method, value);
355}
356
357// Set code_off to 0 for the method.
358static void RemoveCode(DexFile* dex_file, const char* method) {
359 const uint8_t* ptr = FindMethodData(dex_file, method);
360 // Next is flags, pass.
361 DecodeUnsignedLeb128(&ptr);
362
363 // Figure out how many bytes the code_off is.
364 const uint8_t* tmp = ptr;
365 DecodeUnsignedLeb128(&tmp);
366 size_t bytes = tmp - ptr;
367
368 uint8_t* mod = const_cast<uint8_t*>(ptr);
369 for (size_t i = 1; i < bytes; ++i) {
370 *(mod++) = 0x80;
Andreas Gampedf10b322014-06-11 21:46:05 -0700371 }
Andreas Gampee6215c02015-08-31 18:54:38 -0700372 *mod = 0x00;
373}
374
375TEST_F(DexFileVerifierTest, MethodAccessFlagsBase) {
376 // Check that it's OK when the wrong declared-synchronized flag is removed from "foo."
377 VerifyModification(
378 kMethodFlagsTestDex,
379 "method_flags_ok",
380 [](DexFile* dex_file) {
381 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
382 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
383 },
384 nullptr);
385}
386
387TEST_F(DexFileVerifierTest, MethodAccessFlagsConstructors) {
388 // Make sure we still accept constructors without their flags.
389 VerifyModification(
390 kMethodFlagsTestDex,
391 "method_flags_missing_constructor_tag_ok",
392 [](DexFile* dex_file) {
393 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
394 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
395
396 ApplyMaskToMethodFlags(dex_file, "<init>", ~kAccConstructor);
397 ApplyMaskToMethodFlags(dex_file, "<clinit>", ~kAccConstructor);
398 },
399 nullptr);
400
401 constexpr const char* kConstructors[] = { "<clinit>", "<init>"};
402 for (size_t i = 0; i < 2; ++i) {
403 // Constructor with code marked native.
404 VerifyModification(
405 kMethodFlagsTestDex,
406 "method_flags_constructor_native",
407 [&](DexFile* dex_file) {
408 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
409 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
410
411 OrMaskToMethodFlags(dex_file, kConstructors[i], kAccNative);
412 },
413 "has code, but is marked native or abstract");
414 // Constructor with code marked abstract.
415 VerifyModification(
416 kMethodFlagsTestDex,
417 "method_flags_constructor_abstract",
418 [&](DexFile* dex_file) {
419 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
420 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
421
422 OrMaskToMethodFlags(dex_file, kConstructors[i], kAccAbstract);
423 },
424 "has code, but is marked native or abstract");
425 // Constructor as-is without code.
426 VerifyModification(
427 kMethodFlagsTestDex,
428 "method_flags_constructor_nocode",
429 [&](DexFile* dex_file) {
430 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
431 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
432
433 RemoveCode(dex_file, kConstructors[i]);
434 },
435 "has no code, but is not marked native or abstract");
436 // Constructor without code marked native.
437 VerifyModification(
438 kMethodFlagsTestDex,
439 "method_flags_constructor_native_nocode",
440 [&](DexFile* dex_file) {
441 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
442 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
443
444 OrMaskToMethodFlags(dex_file, kConstructors[i], kAccNative);
445 RemoveCode(dex_file, kConstructors[i]);
446 },
447 "must not be abstract or native");
448 // Constructor without code marked abstract.
449 VerifyModification(
450 kMethodFlagsTestDex,
451 "method_flags_constructor_abstract_nocode",
452 [&](DexFile* dex_file) {
453 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
454 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
455
456 OrMaskToMethodFlags(dex_file, kConstructors[i], kAccAbstract);
457 RemoveCode(dex_file, kConstructors[i]);
458 },
459 "must not be abstract or native");
460 }
461 // <init> may only have (modulo ignored):
462 // kAccPrivate | kAccProtected | kAccPublic | kAccStrict | kAccVarargs | kAccSynthetic
463 static constexpr uint32_t kInitAllowed[] = {
464 0,
465 kAccPrivate,
466 kAccProtected,
467 kAccPublic,
468 kAccStrict,
469 kAccVarargs,
470 kAccSynthetic
471 };
472 for (size_t i = 0; i < arraysize(kInitAllowed); ++i) {
473 VerifyModification(
474 kMethodFlagsTestDex,
475 "init_allowed_flags",
476 [&](DexFile* dex_file) {
477 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
478 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
479
480 ApplyMaskToMethodFlags(dex_file, "<init>", ~kAccPublic);
481 OrMaskToMethodFlags(dex_file, "<init>", kInitAllowed[i]);
482 },
483 nullptr);
484 }
485 // Only one of public-private-protected.
486 for (size_t i = 1; i < 8; ++i) {
487 if (POPCOUNT(i) < 2) {
488 continue;
489 }
490 // Technically the flags match, but just be defensive here.
491 uint32_t mask = ((i & 1) != 0 ? kAccPrivate : 0) |
492 ((i & 2) != 0 ? kAccProtected : 0) |
493 ((i & 4) != 0 ? kAccPublic : 0);
494 VerifyModification(
495 kMethodFlagsTestDex,
496 "init_one_of_ppp",
497 [&](DexFile* dex_file) {
498 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
499 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
500
501 ApplyMaskToMethodFlags(dex_file, "<init>", ~kAccPublic);
502 OrMaskToMethodFlags(dex_file, "<init>", mask);
503 },
504 "Method may have only one of public/protected/private");
505 }
506 // <init> doesn't allow
507 // kAccStatic | kAccFinal | kAccSynchronized | kAccBridge
508 // Need to handle static separately as it has its own error message.
509 VerifyModification(
510 kMethodFlagsTestDex,
511 "init_not_allowed_flags",
512 [&](DexFile* dex_file) {
513 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
514 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
515
516 ApplyMaskToMethodFlags(dex_file, "<init>", ~kAccPublic);
517 OrMaskToMethodFlags(dex_file, "<init>", kAccStatic);
518 },
Andreas Gampec9f0ba12016-02-09 09:21:04 -0800519 "Constructor 1(LMethodFlags;.<init>) is not flagged correctly wrt/ static");
Andreas Gampee6215c02015-08-31 18:54:38 -0700520 static constexpr uint32_t kInitNotAllowed[] = {
521 kAccFinal,
522 kAccSynchronized,
523 kAccBridge
524 };
525 for (size_t i = 0; i < arraysize(kInitNotAllowed); ++i) {
526 VerifyModification(
527 kMethodFlagsTestDex,
528 "init_not_allowed_flags",
529 [&](DexFile* dex_file) {
530 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
531 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
532
533 ApplyMaskToMethodFlags(dex_file, "<init>", ~kAccPublic);
534 OrMaskToMethodFlags(dex_file, "<init>", kInitNotAllowed[i]);
535 },
Andreas Gampec9f0ba12016-02-09 09:21:04 -0800536 "Constructor 1(LMethodFlags;.<init>) flagged inappropriately");
Andreas Gampee6215c02015-08-31 18:54:38 -0700537 }
538}
539
540TEST_F(DexFileVerifierTest, MethodAccessFlagsMethods) {
541 constexpr const char* kMethods[] = { "foo", "bar"};
542 for (size_t i = 0; i < arraysize(kMethods); ++i) {
543 // Make sure we reject non-constructors marked as constructors.
544 VerifyModification(
545 kMethodFlagsTestDex,
546 "method_flags_non_constructor",
547 [&](DexFile* dex_file) {
548 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
549 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
550
551 OrMaskToMethodFlags(dex_file, kMethods[i], kAccConstructor);
552 },
553 "is marked constructor, but doesn't match name");
554
555 VerifyModification(
556 kMethodFlagsTestDex,
557 "method_flags_native_with_code",
558 [&](DexFile* dex_file) {
559 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
560 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
561
562 OrMaskToMethodFlags(dex_file, kMethods[i], kAccNative);
563 },
564 "has code, but is marked native or abstract");
565
566 VerifyModification(
567 kMethodFlagsTestDex,
568 "method_flags_abstract_with_code",
569 [&](DexFile* dex_file) {
570 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
571 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
572
573 OrMaskToMethodFlags(dex_file, kMethods[i], kAccAbstract);
574 },
575 "has code, but is marked native or abstract");
576
577 VerifyModification(
578 kMethodFlagsTestDex,
579 "method_flags_non_abstract_native_no_code",
580 [&](DexFile* dex_file) {
581 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
582 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
583
584 RemoveCode(dex_file, kMethods[i]);
585 },
586 "has no code, but is not marked native or abstract");
587
588 // Abstract methods may not have the following flags.
589 constexpr uint32_t kAbstractDisallowed[] = {
590 kAccPrivate,
591 kAccStatic,
592 kAccFinal,
593 kAccNative,
594 kAccStrict,
595 kAccSynchronized,
596 };
597 for (size_t j = 0; j < arraysize(kAbstractDisallowed); ++j) {
598 VerifyModification(
599 kMethodFlagsTestDex,
600 "method_flags_abstract_and_disallowed_no_code",
601 [&](DexFile* dex_file) {
602 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
603 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
604
605 RemoveCode(dex_file, kMethods[i]);
606
607 // Can't check private and static with foo, as it's in the virtual list and gives a
608 // different error.
609 if (((GetMethodFlags(dex_file, kMethods[i]) & kAccPublic) != 0) &&
610 ((kAbstractDisallowed[j] & (kAccPrivate | kAccStatic)) != 0)) {
611 // Use another breaking flag.
612 OrMaskToMethodFlags(dex_file, kMethods[i], kAccAbstract | kAccFinal);
613 } else {
614 OrMaskToMethodFlags(dex_file, kMethods[i], kAccAbstract | kAbstractDisallowed[j]);
615 }
616 },
617 "has disallowed access flags");
618 }
619
620 // Only one of public-private-protected.
621 for (size_t j = 1; j < 8; ++j) {
622 if (POPCOUNT(j) < 2) {
623 continue;
624 }
625 // Technically the flags match, but just be defensive here.
626 uint32_t mask = ((j & 1) != 0 ? kAccPrivate : 0) |
627 ((j & 2) != 0 ? kAccProtected : 0) |
628 ((j & 4) != 0 ? kAccPublic : 0);
629 VerifyModification(
630 kMethodFlagsTestDex,
631 "method_flags_one_of_ppp",
632 [&](DexFile* dex_file) {
633 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
634 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
635
636 ApplyMaskToMethodFlags(dex_file, kMethods[i], ~kAccPublic);
637 OrMaskToMethodFlags(dex_file, kMethods[i], mask);
638 },
639 "Method may have only one of public/protected/private");
640 }
641 }
642}
643
644TEST_F(DexFileVerifierTest, MethodAccessFlagsIgnoredOK) {
645 constexpr const char* kMethods[] = { "<clinit>", "<init>", "foo", "bar"};
646 for (size_t i = 0; i < arraysize(kMethods); ++i) {
647 // All interesting method flags, other flags are to be ignored.
648 constexpr uint32_t kAllMethodFlags =
649 kAccPublic |
650 kAccPrivate |
651 kAccProtected |
652 kAccStatic |
653 kAccFinal |
654 kAccSynchronized |
655 kAccBridge |
656 kAccVarargs |
657 kAccNative |
658 kAccAbstract |
659 kAccStrict |
660 kAccSynthetic;
661 constexpr uint32_t kIgnoredMask = ~kAllMethodFlags & 0xFFFF;
662 VerifyModification(
663 kMethodFlagsTestDex,
664 "method_flags_ignored",
665 [&](DexFile* dex_file) {
666 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
667 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
668
669 OrMaskToMethodFlags(dex_file, kMethods[i], kIgnoredMask);
670 },
671 nullptr);
672 }
673}
674
Vladimir Marko59399ab2016-05-03 16:31:52 +0100675TEST_F(DexFileVerifierTest, B28552165) {
676 // Regression test for bad error string retrieval in different situations.
677 // Using invalid access flags to trigger the error.
678 VerifyModification(
679 kMethodFlagsTestDex,
680 "b28552165",
681 [](DexFile* dex_file) {
682 OrMaskToMethodFlags(dex_file, "foo", kAccPublic | kAccProtected);
683 uint32_t method_idx;
684 FindMethodData(dex_file, "foo", &method_idx);
685 auto* method_id = const_cast<DexFile::MethodId*>(&dex_file->GetMethodId(method_idx));
686 method_id->name_idx_ = dex_file->NumStringIds();
687 },
688 "Method may have only one of public/protected/private, LMethodFlags;.(error)");
689}
690
Andreas Gampee6215c02015-08-31 18:54:38 -0700691// Set of dex files for interface method tests. As it's not as easy to mutate method names, it's
692// just easier to break up bad cases.
693
Andreas Gampee6215c02015-08-31 18:54:38 -0700694// Standard interface. Use declared-synchronized again for 3B encoding.
695//
696// .class public interface LInterfaceMethodFlags;
697// .super Ljava/lang/Object;
698//
699// .method public static constructor <clinit>()V
700// .registers 1
701// return-void
702// .end method
703//
704// .method public abstract declared-synchronized foo()V
705// .end method
706static const char kMethodFlagsInterface[] =
707 "ZGV4CjAzNQCOM0odZ5bws1d9GSmumXaK5iE/7XxFpOm8AQAAcAAAAHhWNBIAAAAAAAAAADQBAAAF"
708 "AAAAcAAAAAMAAACEAAAAAQAAAJAAAAAAAAAAAAAAAAIAAACcAAAAAQAAAKwAAADwAAAAzAAAAMwA"
709 "AADWAAAA7gAAAAIBAAAFAQAAAQAAAAIAAAADAAAAAwAAAAIAAAAAAAAAAAAAAAAAAAAAAAAABAAA"
710 "AAAAAAABAgAAAQAAAAAAAAD/////AAAAACIBAAAAAAAACDxjbGluaXQ+ABZMSW50ZXJmYWNlTWV0"
711 "aG9kRmxhZ3M7ABJMamF2YS9sYW5nL09iamVjdDsAAVYAA2ZvbwAAAAAAAAABAAAAAAAAAAAAAAAB"
712 "AAAADgAAAAEBAImABJACAYGICAAAAAALAAAAAAAAAAEAAAAAAAAAAQAAAAUAAABwAAAAAgAAAAMA"
713 "AACEAAAAAwAAAAEAAACQAAAABQAAAAIAAACcAAAABgAAAAEAAACsAAAAAiAAAAUAAADMAAAAAxAA"
714 "AAEAAAAMAQAAASAAAAEAAAAQAQAAACAAAAEAAAAiAQAAABAAAAEAAAA0AQAA";
715
716// To simplify generation of interesting "sub-states" of src_value, allow a "simple" mask to apply
717// to a src_value, such that mask bit 0 applies to the lowest set bit in src_value, and so on.
718static uint32_t ApplyMaskShifted(uint32_t src_value, uint32_t mask) {
719 uint32_t result = 0;
720 uint32_t mask_index = 0;
721 while (src_value != 0) {
722 uint32_t index = CTZ(src_value);
723 if (((src_value & (1 << index)) != 0) &&
724 ((mask & (1 << mask_index)) != 0)) {
725 result |= (1 << index);
726 }
727 src_value &= ~(1 << index);
728 mask_index++;
729 }
730 return result;
731}
732
Andreas Gampe76ed99d2016-03-28 18:31:29 -0700733// Make the Dex file version 37.
734static void MakeDexVersion37(DexFile* dex_file) {
735 size_t offset = OFFSETOF_MEMBER(DexFile::Header, magic_) + 6;
736 CHECK_EQ(*(dex_file->Begin() + offset), '5');
737 *(const_cast<uint8_t*>(dex_file->Begin()) + offset) = '7';
738}
739
Andreas Gampee6215c02015-08-31 18:54:38 -0700740TEST_F(DexFileVerifierTest, MethodAccessFlagsInterfaces) {
Andreas Gampee6215c02015-08-31 18:54:38 -0700741 VerifyModification(
742 kMethodFlagsInterface,
743 "method_flags_interface_ok",
744 [](DexFile* dex_file) {
745 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
746 },
747 nullptr);
Andreas Gampe76ed99d2016-03-28 18:31:29 -0700748 VerifyModification(
749 kMethodFlagsInterface,
750 "method_flags_interface_ok37",
751 [](DexFile* dex_file) {
752 MakeDexVersion37(dex_file);
753 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
754 },
755 nullptr);
Andreas Gampee6215c02015-08-31 18:54:38 -0700756
757 VerifyModification(
758 kMethodFlagsInterface,
759 "method_flags_interface_non_public",
760 [](DexFile* dex_file) {
761 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
762
763 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccPublic);
764 },
Andreas Gampe76ed99d2016-03-28 18:31:29 -0700765 nullptr); // Should be allowed in older dex versions for backwards compatibility.
766 VerifyModification(
767 kMethodFlagsInterface,
768 "method_flags_interface_non_public",
769 [](DexFile* dex_file) {
770 MakeDexVersion37(dex_file);
771 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
772
773 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccPublic);
774 },
Alex Lightd7c10c22016-03-31 10:03:07 -0700775 "Interface virtual method 1(LInterfaceMethodFlags;.foo) is not public");
Andreas Gampe76ed99d2016-03-28 18:31:29 -0700776
Andreas Gampee6215c02015-08-31 18:54:38 -0700777 VerifyModification(
778 kMethodFlagsInterface,
779 "method_flags_interface_non_abstract",
780 [](DexFile* dex_file) {
781 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
782
783 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccAbstract);
784 },
Andreas Gampec9f0ba12016-02-09 09:21:04 -0800785 "Method 1(LInterfaceMethodFlags;.foo) has no code, but is not marked native or abstract");
Andreas Gampee6215c02015-08-31 18:54:38 -0700786
787 VerifyModification(
788 kMethodFlagsInterface,
789 "method_flags_interface_static",
790 [](DexFile* dex_file) {
791 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
792
793 OrMaskToMethodFlags(dex_file, "foo", kAccStatic);
794 },
Andreas Gampec9f0ba12016-02-09 09:21:04 -0800795 "Direct/virtual method 1(LInterfaceMethodFlags;.foo) not in expected list 0");
Andreas Gampee6215c02015-08-31 18:54:38 -0700796 VerifyModification(
797 kMethodFlagsInterface,
798 "method_flags_interface_private",
799 [](DexFile* dex_file) {
800 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
801
802 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccPublic);
803 OrMaskToMethodFlags(dex_file, "foo", kAccPrivate);
804 },
Andreas Gampec9f0ba12016-02-09 09:21:04 -0800805 "Direct/virtual method 1(LInterfaceMethodFlags;.foo) not in expected list 0");
Andreas Gampee6215c02015-08-31 18:54:38 -0700806
807 VerifyModification(
808 kMethodFlagsInterface,
809 "method_flags_interface_non_public",
810 [](DexFile* dex_file) {
811 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
812
813 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccPublic);
814 },
Andreas Gampe76ed99d2016-03-28 18:31:29 -0700815 nullptr); // Should be allowed in older dex versions for backwards compatibility.
816 VerifyModification(
817 kMethodFlagsInterface,
818 "method_flags_interface_non_public",
819 [](DexFile* dex_file) {
820 MakeDexVersion37(dex_file);
821 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
822
823 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccPublic);
824 },
Alex Lightd7c10c22016-03-31 10:03:07 -0700825 "Interface virtual method 1(LInterfaceMethodFlags;.foo) is not public");
Andreas Gampe76ed99d2016-03-28 18:31:29 -0700826
Andreas Gampee6215c02015-08-31 18:54:38 -0700827 VerifyModification(
828 kMethodFlagsInterface,
829 "method_flags_interface_protected",
830 [](DexFile* dex_file) {
831 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
832
833 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccPublic);
834 OrMaskToMethodFlags(dex_file, "foo", kAccProtected);
835 },
Andreas Gampe76ed99d2016-03-28 18:31:29 -0700836 nullptr); // Should be allowed in older dex versions for backwards compatibility.
837 VerifyModification(
838 kMethodFlagsInterface,
839 "method_flags_interface_protected",
840 [](DexFile* dex_file) {
841 MakeDexVersion37(dex_file);
842 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
843
844 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccPublic);
845 OrMaskToMethodFlags(dex_file, "foo", kAccProtected);
846 },
Alex Lightd7c10c22016-03-31 10:03:07 -0700847 "Interface virtual method 1(LInterfaceMethodFlags;.foo) is not public");
Andreas Gampee6215c02015-08-31 18:54:38 -0700848
849 constexpr uint32_t kAllMethodFlags =
850 kAccPublic |
851 kAccPrivate |
852 kAccProtected |
853 kAccStatic |
854 kAccFinal |
855 kAccSynchronized |
856 kAccBridge |
857 kAccVarargs |
858 kAccNative |
859 kAccAbstract |
860 kAccStrict |
861 kAccSynthetic;
862 constexpr uint32_t kInterfaceMethodFlags =
863 kAccPublic | kAccAbstract | kAccVarargs | kAccBridge | kAccSynthetic;
864 constexpr uint32_t kInterfaceDisallowed = kAllMethodFlags &
865 ~kInterfaceMethodFlags &
866 // Already tested, needed to be separate.
867 ~kAccStatic &
868 ~kAccPrivate &
869 ~kAccProtected;
870 static_assert(kInterfaceDisallowed != 0, "There should be disallowed flags.");
871
872 uint32_t bits = POPCOUNT(kInterfaceDisallowed);
873 for (uint32_t i = 1; i < (1u << bits); ++i) {
874 VerifyModification(
875 kMethodFlagsInterface,
876 "method_flags_interface_non_abstract",
877 [&](DexFile* dex_file) {
878 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
879
880 uint32_t mask = ApplyMaskShifted(kInterfaceDisallowed, i);
881 if ((mask & kAccProtected) != 0) {
882 mask &= ~kAccProtected;
883 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccPublic);
884 }
885 OrMaskToMethodFlags(dex_file, "foo", mask);
886 },
Andreas Gampec9f0ba12016-02-09 09:21:04 -0800887 "Abstract method 1(LInterfaceMethodFlags;.foo) has disallowed access flags");
Andreas Gampee6215c02015-08-31 18:54:38 -0700888 }
889}
890
891///////////////////////////////////////////////////////////////////
892
893// Field flags.
894
895// Find the method data for the first method with the given name (from class 0). Note: the pointer
896// is to the access flags, so that the caller doesn't have to handle the leb128-encoded method-index
897// delta.
898static const uint8_t* FindFieldData(const DexFile* dex_file, const char* name) {
899 const DexFile::ClassDef& class_def = dex_file->GetClassDef(0);
900 const uint8_t* class_data = dex_file->GetClassData(class_def);
901
902 ClassDataItemIterator it(*dex_file, class_data);
903
904 const uint8_t* trailing = class_data;
905 // Need to manually decode the four entries. DataPointer() doesn't work for this, as the first
906 // element has already been loaded into the iterator.
907 DecodeUnsignedLeb128(&trailing);
908 DecodeUnsignedLeb128(&trailing);
909 DecodeUnsignedLeb128(&trailing);
910 DecodeUnsignedLeb128(&trailing);
911
912 while (it.HasNextStaticField() || it.HasNextInstanceField()) {
913 uint32_t field_index = it.GetMemberIndex();
914 uint32_t name_index = dex_file->GetFieldId(field_index).name_idx_;
915 const DexFile::StringId& string_id = dex_file->GetStringId(name_index);
916 const char* str = dex_file->GetStringData(string_id);
917 if (strcmp(name, str) == 0) {
918 DecodeUnsignedLeb128(&trailing);
919 return trailing;
920 }
921
922 trailing = it.DataPointer();
923 it.Next();
924 }
925
926 return nullptr;
927}
928
929// Set the method flags to the given value.
930static void SetFieldFlags(DexFile* dex_file, const char* field, uint32_t mask) {
931 uint8_t* field_flags_ptr = const_cast<uint8_t*>(FindFieldData(dex_file, field));
932 CHECK(field_flags_ptr != nullptr) << field;
933
934 // Unroll this, as we only have three bytes, anyways.
935 uint8_t base1 = static_cast<uint8_t>(mask & 0x7F);
936 *(field_flags_ptr++) = (base1 | 0x80);
937 mask >>= 7;
938
939 uint8_t base2 = static_cast<uint8_t>(mask & 0x7F);
940 *(field_flags_ptr++) = (base2 | 0x80);
941 mask >>= 7;
942
943 uint8_t base3 = static_cast<uint8_t>(mask & 0x7F);
944 *field_flags_ptr = base3;
945}
946
947static uint32_t GetFieldFlags(DexFile* dex_file, const char* field) {
948 const uint8_t* field_flags_ptr = const_cast<uint8_t*>(FindFieldData(dex_file, field));
949 CHECK(field_flags_ptr != nullptr) << field;
950 return DecodeUnsignedLeb128(&field_flags_ptr);
951}
952
953// Apply the given mask to method flags.
954static void ApplyMaskToFieldFlags(DexFile* dex_file, const char* field, uint32_t mask) {
955 uint32_t value = GetFieldFlags(dex_file, field);
956 value &= mask;
957 SetFieldFlags(dex_file, field, value);
958}
959
960// Apply the given mask to method flags.
961static void OrMaskToFieldFlags(DexFile* dex_file, const char* field, uint32_t mask) {
962 uint32_t value = GetFieldFlags(dex_file, field);
963 value |= mask;
964 SetFieldFlags(dex_file, field, value);
965}
966
967// Standard class. Use declared-synchronized again for 3B encoding.
968//
969// .class public LFieldFlags;
970// .super Ljava/lang/Object;
971//
972// .field declared-synchronized public foo:I
973//
974// .field declared-synchronized public static bar:I
975
976static const char kFieldFlagsTestDex[] =
977 "ZGV4CjAzNQBtLw7hydbfv4TdXidZyzAB70W7w3vnYJRwAQAAcAAAAHhWNBIAAAAAAAAAAAABAAAF"
978 "AAAAcAAAAAMAAACEAAAAAAAAAAAAAAACAAAAkAAAAAAAAAAAAAAAAQAAAKAAAACwAAAAwAAAAMAA"
979 "AADDAAAA0QAAAOUAAADqAAAAAAAAAAEAAAACAAAAAQAAAAMAAAABAAAABAAAAAEAAAABAAAAAgAA"
980 "AAAAAAD/////AAAAAPQAAAAAAAAAAUkADExGaWVsZEZsYWdzOwASTGphdmEvbGFuZy9PYmplY3Q7"
981 "AANiYXIAA2ZvbwAAAAAAAAEBAAAAiYAIAYGACAkAAAAAAAAAAQAAAAAAAAABAAAABQAAAHAAAAAC"
982 "AAAAAwAAAIQAAAAEAAAAAgAAAJAAAAAGAAAAAQAAAKAAAAACIAAABQAAAMAAAAADEAAAAQAAAPAA"
983 "AAAAIAAAAQAAAPQAAAAAEAAAAQAAAAABAAA=";
984
985TEST_F(DexFileVerifierTest, FieldAccessFlagsBase) {
986 // Check that it's OK when the wrong declared-synchronized flag is removed from "foo."
987 VerifyModification(
988 kFieldFlagsTestDex,
989 "field_flags_ok",
990 [](DexFile* dex_file) {
991 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
992 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
993 },
994 nullptr);
995}
996
997TEST_F(DexFileVerifierTest, FieldAccessFlagsWrongList) {
998 // Mark the field so that it should appear in the opposite list (instance vs static).
999 VerifyModification(
1000 kFieldFlagsTestDex,
1001 "field_flags_wrong_list",
1002 [](DexFile* dex_file) {
1003 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1004 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
1005
1006 OrMaskToFieldFlags(dex_file, "foo", kAccStatic);
1007 },
1008 "Static/instance field not in expected list");
1009 VerifyModification(
1010 kFieldFlagsTestDex,
1011 "field_flags_wrong_list",
1012 [](DexFile* dex_file) {
1013 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1014 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
1015
1016 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccStatic);
1017 },
1018 "Static/instance field not in expected list");
1019}
1020
1021TEST_F(DexFileVerifierTest, FieldAccessFlagsPPP) {
1022 static const char* kFields[] = { "foo", "bar" };
1023 for (size_t i = 0; i < arraysize(kFields); ++i) {
1024 // Should be OK to remove public.
1025 VerifyModification(
1026 kFieldFlagsTestDex,
1027 "field_flags_non_public",
1028 [&](DexFile* dex_file) {
1029 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1030 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
1031
1032 ApplyMaskToFieldFlags(dex_file, kFields[i], ~kAccPublic);
1033 },
1034 nullptr);
1035 constexpr uint32_t kAccFlags = kAccPublic | kAccPrivate | kAccProtected;
1036 uint32_t bits = POPCOUNT(kAccFlags);
1037 for (uint32_t j = 1; j < (1u << bits); ++j) {
1038 if (POPCOUNT(j) < 2) {
1039 continue;
1040 }
1041 VerifyModification(
1042 kFieldFlagsTestDex,
1043 "field_flags_ppp",
1044 [&](DexFile* dex_file) {
1045 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1046 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
1047
1048 ApplyMaskToFieldFlags(dex_file, kFields[i], ~kAccPublic);
1049 uint32_t mask = ApplyMaskShifted(kAccFlags, j);
1050 OrMaskToFieldFlags(dex_file, kFields[i], mask);
1051 },
1052 "Field may have only one of public/protected/private");
1053 }
1054 }
1055}
1056
1057TEST_F(DexFileVerifierTest, FieldAccessFlagsIgnoredOK) {
1058 constexpr const char* kFields[] = { "foo", "bar"};
1059 for (size_t i = 0; i < arraysize(kFields); ++i) {
1060 // All interesting method flags, other flags are to be ignored.
1061 constexpr uint32_t kAllFieldFlags =
1062 kAccPublic |
1063 kAccPrivate |
1064 kAccProtected |
1065 kAccStatic |
1066 kAccFinal |
1067 kAccVolatile |
1068 kAccTransient |
1069 kAccSynthetic |
1070 kAccEnum;
1071 constexpr uint32_t kIgnoredMask = ~kAllFieldFlags & 0xFFFF;
1072 VerifyModification(
1073 kFieldFlagsTestDex,
1074 "field_flags_ignored",
1075 [&](DexFile* dex_file) {
1076 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1077 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
1078
1079 OrMaskToFieldFlags(dex_file, kFields[i], kIgnoredMask);
1080 },
1081 nullptr);
1082 }
1083}
1084
1085TEST_F(DexFileVerifierTest, FieldAccessFlagsVolatileFinal) {
1086 constexpr const char* kFields[] = { "foo", "bar"};
1087 for (size_t i = 0; i < arraysize(kFields); ++i) {
1088 VerifyModification(
1089 kFieldFlagsTestDex,
1090 "field_flags_final_and_volatile",
1091 [&](DexFile* dex_file) {
1092 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1093 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
1094
1095 OrMaskToFieldFlags(dex_file, kFields[i], kAccVolatile | kAccFinal);
1096 },
1097 "Fields may not be volatile and final");
1098 }
1099}
1100
1101// Standard interface. Needs to be separate from class as interfaces do not allow instance fields.
1102// Use declared-synchronized again for 3B encoding.
1103//
1104// .class public interface LInterfaceFieldFlags;
1105// .super Ljava/lang/Object;
1106//
1107// .field declared-synchronized public static final foo:I
1108
1109static const char kFieldFlagsInterfaceTestDex[] =
1110 "ZGV4CjAzNQCVMHfEimR1zZPk6hl6O9GPAYqkl3u0umFkAQAAcAAAAHhWNBIAAAAAAAAAAPQAAAAE"
1111 "AAAAcAAAAAMAAACAAAAAAAAAAAAAAAABAAAAjAAAAAAAAAAAAAAAAQAAAJQAAACwAAAAtAAAALQA"
1112 "AAC3AAAAzgAAAOIAAAAAAAAAAQAAAAIAAAABAAAAAwAAAAEAAAABAgAAAgAAAAAAAAD/////AAAA"
1113 "AOwAAAAAAAAAAUkAFUxJbnRlcmZhY2VGaWVsZEZsYWdzOwASTGphdmEvbGFuZy9PYmplY3Q7AANm"
1114 "b28AAAAAAAABAAAAAJmACAkAAAAAAAAAAQAAAAAAAAABAAAABAAAAHAAAAACAAAAAwAAAIAAAAAE"
1115 "AAAAAQAAAIwAAAAGAAAAAQAAAJQAAAACIAAABAAAALQAAAADEAAAAQAAAOgAAAAAIAAAAQAAAOwA"
1116 "AAAAEAAAAQAAAPQAAAA=";
1117
1118TEST_F(DexFileVerifierTest, FieldAccessFlagsInterface) {
1119 VerifyModification(
1120 kFieldFlagsInterfaceTestDex,
1121 "field_flags_interface",
1122 [](DexFile* dex_file) {
1123 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1124 },
1125 nullptr);
Andreas Gampe76ed99d2016-03-28 18:31:29 -07001126 VerifyModification(
1127 kFieldFlagsInterfaceTestDex,
1128 "field_flags_interface",
1129 [](DexFile* dex_file) {
1130 MakeDexVersion37(dex_file);
1131 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1132 },
1133 nullptr);
Andreas Gampee6215c02015-08-31 18:54:38 -07001134
1135 VerifyModification(
1136 kFieldFlagsInterfaceTestDex,
1137 "field_flags_interface_non_public",
1138 [](DexFile* dex_file) {
1139 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1140
1141 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccPublic);
1142 },
Andreas Gampe76ed99d2016-03-28 18:31:29 -07001143 nullptr); // Should be allowed in older dex versions for backwards compatibility.
1144 VerifyModification(
1145 kFieldFlagsInterfaceTestDex,
1146 "field_flags_interface_non_public",
1147 [](DexFile* dex_file) {
1148 MakeDexVersion37(dex_file);
1149 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1150
1151 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccPublic);
1152 },
Andreas Gampee6215c02015-08-31 18:54:38 -07001153 "Interface field is not public final static");
Andreas Gampe76ed99d2016-03-28 18:31:29 -07001154
Andreas Gampee6215c02015-08-31 18:54:38 -07001155 VerifyModification(
1156 kFieldFlagsInterfaceTestDex,
1157 "field_flags_interface_non_final",
1158 [](DexFile* dex_file) {
1159 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1160
1161 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccFinal);
1162 },
Andreas Gampe76ed99d2016-03-28 18:31:29 -07001163 nullptr); // Should be allowed in older dex versions for backwards compatibility.
1164 VerifyModification(
1165 kFieldFlagsInterfaceTestDex,
1166 "field_flags_interface_non_final",
1167 [](DexFile* dex_file) {
1168 MakeDexVersion37(dex_file);
1169 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1170
1171 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccFinal);
1172 },
Andreas Gampee6215c02015-08-31 18:54:38 -07001173 "Interface field is not public final static");
Andreas Gampe76ed99d2016-03-28 18:31:29 -07001174
Andreas Gampee6215c02015-08-31 18:54:38 -07001175 VerifyModification(
1176 kFieldFlagsInterfaceTestDex,
1177 "field_flags_interface_protected",
1178 [](DexFile* dex_file) {
1179 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1180
1181 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccPublic);
1182 OrMaskToFieldFlags(dex_file, "foo", kAccProtected);
1183 },
Andreas Gampe76ed99d2016-03-28 18:31:29 -07001184 nullptr); // Should be allowed in older dex versions for backwards compatibility.
1185 VerifyModification(
1186 kFieldFlagsInterfaceTestDex,
1187 "field_flags_interface_protected",
1188 [](DexFile* dex_file) {
1189 MakeDexVersion37(dex_file);
1190 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1191
1192 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccPublic);
1193 OrMaskToFieldFlags(dex_file, "foo", kAccProtected);
1194 },
Andreas Gampee6215c02015-08-31 18:54:38 -07001195 "Interface field is not public final static");
Andreas Gampe76ed99d2016-03-28 18:31:29 -07001196
Andreas Gampee6215c02015-08-31 18:54:38 -07001197 VerifyModification(
1198 kFieldFlagsInterfaceTestDex,
1199 "field_flags_interface_private",
1200 [](DexFile* dex_file) {
1201 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1202
1203 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccPublic);
1204 OrMaskToFieldFlags(dex_file, "foo", kAccPrivate);
1205 },
Andreas Gampe76ed99d2016-03-28 18:31:29 -07001206 nullptr); // Should be allowed in older dex versions for backwards compatibility.
1207 VerifyModification(
1208 kFieldFlagsInterfaceTestDex,
1209 "field_flags_interface_private",
1210 [](DexFile* dex_file) {
1211 MakeDexVersion37(dex_file);
1212 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1213
1214 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccPublic);
1215 OrMaskToFieldFlags(dex_file, "foo", kAccPrivate);
1216 },
Andreas Gampee6215c02015-08-31 18:54:38 -07001217 "Interface field is not public final static");
1218
1219 VerifyModification(
1220 kFieldFlagsInterfaceTestDex,
1221 "field_flags_interface_synthetic",
1222 [](DexFile* dex_file) {
1223 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1224
1225 OrMaskToFieldFlags(dex_file, "foo", kAccSynthetic);
1226 },
1227 nullptr);
1228
1229 constexpr uint32_t kAllFieldFlags =
1230 kAccPublic |
1231 kAccPrivate |
1232 kAccProtected |
1233 kAccStatic |
1234 kAccFinal |
1235 kAccVolatile |
1236 kAccTransient |
1237 kAccSynthetic |
1238 kAccEnum;
1239 constexpr uint32_t kInterfaceFieldFlags = kAccPublic | kAccStatic | kAccFinal | kAccSynthetic;
1240 constexpr uint32_t kInterfaceDisallowed = kAllFieldFlags &
1241 ~kInterfaceFieldFlags &
1242 ~kAccProtected &
1243 ~kAccPrivate;
1244 static_assert(kInterfaceDisallowed != 0, "There should be disallowed flags.");
1245
1246 uint32_t bits = POPCOUNT(kInterfaceDisallowed);
1247 for (uint32_t i = 1; i < (1u << bits); ++i) {
1248 VerifyModification(
1249 kFieldFlagsInterfaceTestDex,
1250 "field_flags_interface_disallowed",
1251 [&](DexFile* dex_file) {
1252 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1253
1254 uint32_t mask = ApplyMaskShifted(kInterfaceDisallowed, i);
1255 if ((mask & kAccProtected) != 0) {
1256 mask &= ~kAccProtected;
1257 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccPublic);
1258 }
1259 OrMaskToFieldFlags(dex_file, "foo", mask);
1260 },
Andreas Gampe76ed99d2016-03-28 18:31:29 -07001261 nullptr); // Should be allowed in older dex versions for backwards compatibility.
1262 VerifyModification(
1263 kFieldFlagsInterfaceTestDex,
1264 "field_flags_interface_disallowed",
1265 [&](DexFile* dex_file) {
1266 MakeDexVersion37(dex_file);
1267 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1268
1269 uint32_t mask = ApplyMaskShifted(kInterfaceDisallowed, i);
1270 if ((mask & kAccProtected) != 0) {
1271 mask &= ~kAccProtected;
1272 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccPublic);
1273 }
1274 OrMaskToFieldFlags(dex_file, "foo", mask);
1275 },
Andreas Gampee6215c02015-08-31 18:54:38 -07001276 "Interface field has disallowed flag");
1277 }
1278}
1279
1280// Standard bad interface. Needs to be separate from class as interfaces do not allow instance
1281// fields. Use declared-synchronized again for 3B encoding.
1282//
1283// .class public interface LInterfaceFieldFlags;
1284// .super Ljava/lang/Object;
1285//
1286// .field declared-synchronized public final foo:I
1287
1288static const char kFieldFlagsInterfaceBadTestDex[] =
1289 "ZGV4CjAzNQByMUnqYKHBkUpvvNp+9CnZ2VyDkKnRN6VkAQAAcAAAAHhWNBIAAAAAAAAAAPQAAAAE"
1290 "AAAAcAAAAAMAAACAAAAAAAAAAAAAAAABAAAAjAAAAAAAAAAAAAAAAQAAAJQAAACwAAAAtAAAALQA"
1291 "AAC3AAAAzgAAAOIAAAAAAAAAAQAAAAIAAAABAAAAAwAAAAEAAAABAgAAAgAAAAAAAAD/////AAAA"
1292 "AOwAAAAAAAAAAUkAFUxJbnRlcmZhY2VGaWVsZEZsYWdzOwASTGphdmEvbGFuZy9PYmplY3Q7AANm"
1293 "b28AAAAAAAAAAQAAAJGACAkAAAAAAAAAAQAAAAAAAAABAAAABAAAAHAAAAACAAAAAwAAAIAAAAAE"
1294 "AAAAAQAAAIwAAAAGAAAAAQAAAJQAAAACIAAABAAAALQAAAADEAAAAQAAAOgAAAAAIAAAAQAAAOwA"
1295 "AAAAEAAAAQAAAPQAAAA=";
1296
1297TEST_F(DexFileVerifierTest, FieldAccessFlagsInterfaceNonStatic) {
1298 VerifyModification(
1299 kFieldFlagsInterfaceBadTestDex,
1300 "field_flags_interface_non_static",
1301 [](DexFile* dex_file) {
1302 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1303 },
Andreas Gampe76ed99d2016-03-28 18:31:29 -07001304 nullptr); // Should be allowed in older dex versions for backwards compatibility.
1305 VerifyModification(
1306 kFieldFlagsInterfaceBadTestDex,
1307 "field_flags_interface_non_static",
1308 [](DexFile* dex_file) {
1309 MakeDexVersion37(dex_file);
1310 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1311 },
Andreas Gampee6215c02015-08-31 18:54:38 -07001312 "Interface field is not public final static");
Andreas Gampedf10b322014-06-11 21:46:05 -07001313}
1314
Logan Chiendd3208d2015-04-19 23:27:52 +08001315// Generated from:
1316//
1317// .class public LTest;
1318// .super Ljava/lang/Object;
1319// .source "Test.java"
1320//
1321// .method public constructor <init>()V
1322// .registers 1
1323//
1324// .prologue
1325// .line 1
1326// invoke-direct {p0}, Ljava/lang/Object;-><init>()V
1327//
1328// return-void
1329// .end method
1330//
1331// .method public static main()V
1332// .registers 2
1333//
1334// const-string v0, "a"
1335// const-string v0, "b"
1336// const-string v0, "c"
1337// const-string v0, "d"
1338// const-string v0, "e"
1339// const-string v0, "f"
1340// const-string v0, "g"
1341// const-string v0, "h"
1342// const-string v0, "i"
1343// const-string v0, "j"
1344// const-string v0, "k"
1345//
1346// .local v1, "local_var":Ljava/lang/String;
1347// const-string v1, "test"
1348// .end method
1349
1350static const char kDebugInfoTestDex[] =
1351 "ZGV4CjAzNQCHRkHix2eIMQgvLD/0VGrlllZLo0Rb6VyUAgAAcAAAAHhWNBIAAAAAAAAAAAwCAAAU"
1352 "AAAAcAAAAAQAAADAAAAAAQAAANAAAAAAAAAAAAAAAAMAAADcAAAAAQAAAPQAAACAAQAAFAEAABQB"
1353 "AAAcAQAAJAEAADgBAABMAQAAVwEAAFoBAABdAQAAYAEAAGMBAABmAQAAaQEAAGwBAABvAQAAcgEA"
1354 "AHUBAAB4AQAAewEAAIYBAACMAQAAAQAAAAIAAAADAAAABQAAAAUAAAADAAAAAAAAAAAAAAAAAAAA"
1355 "AAAAABIAAAABAAAAAAAAAAAAAAABAAAAAQAAAAAAAAAEAAAAAAAAAPwBAAAAAAAABjxpbml0PgAG"
1356 "TFRlc3Q7ABJMamF2YS9sYW5nL09iamVjdDsAEkxqYXZhL2xhbmcvU3RyaW5nOwAJVGVzdC5qYXZh"
1357 "AAFWAAFhAAFiAAFjAAFkAAFlAAFmAAFnAAFoAAFpAAFqAAFrAAlsb2NhbF92YXIABG1haW4ABHRl"
1358 "c3QAAAABAAcOAAAAARYDARIDAAAAAQABAAEAAACUAQAABAAAAHAQAgAAAA4AAgAAAAAAAACZAQAA"
1359 "GAAAABoABgAaAAcAGgAIABoACQAaAAoAGgALABoADAAaAA0AGgAOABoADwAaABAAGgETAAAAAgAA"
1360 "gYAEpAMBCbwDAAALAAAAAAAAAAEAAAAAAAAAAQAAABQAAABwAAAAAgAAAAQAAADAAAAAAwAAAAEA"
1361 "AADQAAAABQAAAAMAAADcAAAABgAAAAEAAAD0AAAAAiAAABQAAAAUAQAAAyAAAAIAAACUAQAAASAA"
1362 "AAIAAACkAQAAACAAAAEAAAD8AQAAABAAAAEAAAAMAgAA";
1363
1364TEST_F(DexFileVerifierTest, DebugInfoTypeIdxTest) {
1365 {
1366 // The input dex file should be good before modification.
1367 ScratchFile tmp;
1368 std::string error_msg;
1369 std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kDebugInfoTestDex,
1370 tmp.GetFilename().c_str(),
1371 &error_msg));
1372 ASSERT_TRUE(raw.get() != nullptr) << error_msg;
1373 }
1374
Andreas Gampee6215c02015-08-31 18:54:38 -07001375 // Modify the debug information entry.
1376 VerifyModification(
1377 kDebugInfoTestDex,
1378 "debug_start_type_idx",
1379 [](DexFile* dex_file) {
1380 *(const_cast<uint8_t*>(dex_file->Begin()) + 416) = 0x14U;
1381 },
1382 "DBG_START_LOCAL type_idx");
Logan Chiendd3208d2015-04-19 23:27:52 +08001383}
1384
Andreas Gampeb512c0e2016-02-19 19:45:34 -08001385TEST_F(DexFileVerifierTest, SectionAlignment) {
1386 {
1387 // The input dex file should be good before modification. Any file is fine, as long as it
1388 // uses all sections.
1389 ScratchFile tmp;
1390 std::string error_msg;
1391 std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kGoodTestDex,
1392 tmp.GetFilename().c_str(),
1393 &error_msg));
1394 ASSERT_TRUE(raw.get() != nullptr) << error_msg;
1395 }
1396
1397 // Modify all section offsets to be unaligned.
1398 constexpr size_t kSections = 7;
1399 for (size_t i = 0; i < kSections; ++i) {
1400 VerifyModification(
1401 kGoodTestDex,
1402 "section_align",
1403 [&](DexFile* dex_file) {
1404 DexFile::Header* header = const_cast<DexFile::Header*>(
1405 reinterpret_cast<const DexFile::Header*>(dex_file->Begin()));
1406 uint32_t* off_ptr;
1407 switch (i) {
1408 case 0:
1409 off_ptr = &header->map_off_;
1410 break;
1411 case 1:
1412 off_ptr = &header->string_ids_off_;
1413 break;
1414 case 2:
1415 off_ptr = &header->type_ids_off_;
1416 break;
1417 case 3:
1418 off_ptr = &header->proto_ids_off_;
1419 break;
1420 case 4:
1421 off_ptr = &header->field_ids_off_;
1422 break;
1423 case 5:
1424 off_ptr = &header->method_ids_off_;
1425 break;
1426 case 6:
1427 off_ptr = &header->class_defs_off_;
1428 break;
1429
1430 static_assert(kSections == 7, "kSections is wrong");
1431 default:
1432 LOG(FATAL) << "Unexpected section";
1433 UNREACHABLE();
1434 }
1435 ASSERT_TRUE(off_ptr != nullptr);
1436 ASSERT_NE(*off_ptr, 0U) << i; // Should already contain a value (in use).
1437 (*off_ptr)++; // Add one, which should misalign it (all the sections
1438 // above are aligned by 4).
1439 },
1440 "should be aligned by 4 for");
1441 }
1442}
1443
Vladimir Marko0ca8add2016-05-03 17:17:50 +01001444// Generated from
1445//
1446// .class LOverloading;
1447//
1448// .super Ljava/lang/Object;
1449//
1450// .method public static foo()V
1451// .registers 1
1452// return-void
1453// .end method
1454//
1455// .method public static foo(I)V
1456// .registers 1
1457// return-void
1458// .end method
1459static const char kProtoOrderingTestDex[] =
1460 "ZGV4CjAzNQA1L+ABE6voQ9Lr4Ci//efB53oGnDr5PinsAQAAcAAAAHhWNBIAAAAAAAAAAFgBAAAG"
1461 "AAAAcAAAAAQAAACIAAAAAgAAAJgAAAAAAAAAAAAAAAIAAACwAAAAAQAAAMAAAAAMAQAA4AAAAOAA"
1462 "AADjAAAA8gAAAAYBAAAJAQAADQEAAAAAAAABAAAAAgAAAAMAAAADAAAAAwAAAAAAAAAEAAAAAwAA"
1463 "ABQBAAABAAAABQAAAAEAAQAFAAAAAQAAAAAAAAACAAAAAAAAAP////8AAAAASgEAAAAAAAABSQAN"
1464 "TE92ZXJsb2FkaW5nOwASTGphdmEvbGFuZy9PYmplY3Q7AAFWAAJWSQADZm9vAAAAAQAAAAAAAAAA"
1465 "AAAAAAAAAAEAAAAAAAAAAAAAAAEAAAAOAAAAAQABAAAAAAAAAAAAAQAAAA4AAAACAAAJpAIBCbgC"
1466 "AAAMAAAAAAAAAAEAAAAAAAAAAQAAAAYAAABwAAAAAgAAAAQAAACIAAAAAwAAAAIAAACYAAAABQAA"
1467 "AAIAAACwAAAABgAAAAEAAADAAAAAAiAAAAYAAADgAAAAARAAAAEAAAAUAQAAAxAAAAIAAAAcAQAA"
1468 "ASAAAAIAAAAkAQAAACAAAAEAAABKAQAAABAAAAEAAABYAQAA";
1469
1470TEST_F(DexFileVerifierTest, ProtoOrdering) {
1471 {
1472 // The input dex file should be good before modification.
1473 ScratchFile tmp;
1474 std::string error_msg;
1475 std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kProtoOrderingTestDex,
1476 tmp.GetFilename().c_str(),
1477 &error_msg));
1478 ASSERT_TRUE(raw.get() != nullptr) << error_msg;
1479 }
1480
1481 // Modify the order of the ProtoIds for two overloads of "foo" with the
1482 // same return type and one having longer parameter list than the other.
1483 for (size_t i = 0; i != 2; ++i) {
1484 VerifyModification(
1485 kProtoOrderingTestDex,
1486 "proto_ordering",
1487 [i](DexFile* dex_file) {
1488 uint32_t method_idx;
1489 const uint8_t* data = FindMethodData(dex_file, "foo", &method_idx);
1490 CHECK(data != nullptr);
1491 // There should be 2 methods called "foo".
1492 CHECK_LT(method_idx + 1u, dex_file->NumMethodIds());
1493 CHECK_EQ(dex_file->GetMethodId(method_idx).name_idx_,
1494 dex_file->GetMethodId(method_idx + 1).name_idx_);
1495 CHECK_EQ(dex_file->GetMethodId(method_idx).proto_idx_ + 1u,
1496 dex_file->GetMethodId(method_idx + 1).proto_idx_);
1497 // Their return types should be the same.
1498 uint32_t proto1_idx = dex_file->GetMethodId(method_idx).proto_idx_;
1499 const DexFile::ProtoId& proto1 = dex_file->GetProtoId(proto1_idx);
1500 const DexFile::ProtoId& proto2 = dex_file->GetProtoId(proto1_idx + 1u);
1501 CHECK_EQ(proto1.return_type_idx_, proto2.return_type_idx_);
1502 // And the first should not have any parameters while the second should have some.
1503 CHECK(!DexFileParameterIterator(*dex_file, proto1).HasNext());
1504 CHECK(DexFileParameterIterator(*dex_file, proto2).HasNext());
1505 if (i == 0) {
1506 // Swap the proto parameters and shorties to break the ordering.
1507 std::swap(const_cast<uint32_t&>(proto1.parameters_off_),
1508 const_cast<uint32_t&>(proto2.parameters_off_));
1509 std::swap(const_cast<uint32_t&>(proto1.shorty_idx_),
1510 const_cast<uint32_t&>(proto2.shorty_idx_));
1511 } else {
1512 // Copy the proto parameters and shorty to create duplicate proto id.
1513 const_cast<uint32_t&>(proto1.parameters_off_) = proto2.parameters_off_;
1514 const_cast<uint32_t&>(proto1.shorty_idx_) = proto2.shorty_idx_;
1515 }
1516 },
1517 "Out-of-order proto_id arguments");
1518 }
1519}
1520
Andreas Gampedf10b322014-06-11 21:46:05 -07001521} // namespace art