blob: 344d186ad4db5c58a8d37043e7c1c2e450b92f66 [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
Ian Rogers13735952014-10-08 12:43:28 -070060static inline uint8_t* DecodeBase64(const char* src, size_t* dst_size) {
61 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());
103 return dst.release();
104}
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
116// Custom deleter. Necessary to clean up the memory we use (to be able to mutate).
117struct DexFileDeleter {
118 void operator()(DexFile* in) {
119 if (in != nullptr) {
Vladimir Marko6958e4f2015-09-17 20:22:02 +0100120 delete[] in->Begin();
Andreas Gampee6215c02015-08-31 18:54:38 -0700121 delete in;
122 }
123 }
124};
125
126using DexFileUniquePtr = std::unique_ptr<DexFile, DexFileDeleter>;
127
128class DexFileVerifierTest : public CommonRuntimeTest {
129 protected:
130 void VerifyModification(const char* dex_file_base64_content,
131 const char* location,
132 std::function<void(DexFile*)> f,
133 const char* expected_error) {
134 DexFileUniquePtr dex_file(WrapAsDexFile(dex_file_base64_content));
135 f(dex_file.get());
136 FixUpChecksum(const_cast<uint8_t*>(dex_file->Begin()));
137
138 std::string error_msg;
139 bool success = DexFileVerifier::Verify(dex_file.get(),
140 dex_file->Begin(),
141 dex_file->Size(),
142 location,
143 &error_msg);
144 if (expected_error == nullptr) {
145 EXPECT_TRUE(success) << error_msg;
146 } else {
147 EXPECT_FALSE(success) << "Expected " << expected_error;
148 if (!success) {
149 EXPECT_NE(error_msg.find(expected_error), std::string::npos) << error_msg;
150 }
151 }
152 }
153
154 private:
155 static DexFile* WrapAsDexFile(const char* dex_file_content_in_base_64) {
156 // Decode base64.
157 size_t length;
158 uint8_t* dex_bytes = DecodeBase64(dex_file_content_in_base_64, &length);
159 CHECK(dex_bytes != nullptr);
160 return new DexFile(dex_bytes, length, "tmp", 0, nullptr, nullptr);
161 }
162};
163
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800164static std::unique_ptr<const DexFile> OpenDexFileBase64(const char* base64,
165 const char* location,
166 std::string* error_msg) {
Andreas Gampedf10b322014-06-11 21:46:05 -0700167 // decode base64
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700168 CHECK(base64 != nullptr);
Andreas Gampedf10b322014-06-11 21:46:05 -0700169 size_t length;
Ian Rogers13735952014-10-08 12:43:28 -0700170 std::unique_ptr<uint8_t[]> dex_bytes(DecodeBase64(base64, &length));
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700171 CHECK(dex_bytes.get() != nullptr);
Andreas Gampedf10b322014-06-11 21:46:05 -0700172
173 // write to provided file
174 std::unique_ptr<File> file(OS::CreateEmptyFile(location));
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700175 CHECK(file.get() != nullptr);
Andreas Gampedf10b322014-06-11 21:46:05 -0700176 if (!file->WriteFully(dex_bytes.get(), length)) {
177 PLOG(FATAL) << "Failed to write base64 as dex file";
178 }
Andreas Gampe4303ba92014-11-06 01:00:46 -0800179 if (file->FlushCloseOrErase() != 0) {
180 PLOG(FATAL) << "Could not flush and close test file.";
181 }
Andreas Gampedf10b322014-06-11 21:46:05 -0700182 file.reset();
183
184 // read dex file
185 ScopedObjectAccess soa(Thread::Current());
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800186 std::vector<std::unique_ptr<const DexFile>> tmp;
Andreas Gampe833a4852014-05-21 18:46:59 -0700187 bool success = DexFile::Open(location, location, error_msg, &tmp);
188 CHECK(success) << error_msg;
189 EXPECT_EQ(1U, tmp.size());
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800190 std::unique_ptr<const DexFile> dex_file = std::move(tmp[0]);
Andreas Gampe833a4852014-05-21 18:46:59 -0700191 EXPECT_EQ(PROT_READ, dex_file->GetPermissions());
192 EXPECT_TRUE(dex_file->IsReadOnly());
193 return dex_file;
Andreas Gampedf10b322014-06-11 21:46:05 -0700194}
195
Andreas Gampedf10b322014-06-11 21:46:05 -0700196// For reference.
197static const char kGoodTestDex[] =
198 "ZGV4CjAzNQDrVbyVkxX1HljTznNf95AglkUAhQuFtmKkAgAAcAAAAHhWNBIAAAAAAAAAAAQCAAAN"
199 "AAAAcAAAAAYAAACkAAAAAgAAALwAAAABAAAA1AAAAAQAAADcAAAAAQAAAPwAAACIAQAAHAEAAFoB"
200 "AABiAQAAagEAAIEBAACVAQAAqQEAAL0BAADDAQAAzgEAANEBAADVAQAA2gEAAN8BAAABAAAAAgAA"
201 "AAMAAAAEAAAABQAAAAgAAAAIAAAABQAAAAAAAAAJAAAABQAAAFQBAAAEAAEACwAAAAAAAAAAAAAA"
202 "AAAAAAoAAAABAAEADAAAAAIAAAAAAAAAAAAAAAEAAAACAAAAAAAAAAcAAAAAAAAA8wEAAAAAAAAB"
203 "AAEAAQAAAOgBAAAEAAAAcBADAAAADgACAAAAAgAAAO0BAAAIAAAAYgAAABoBBgBuIAIAEAAOAAEA"
204 "AAADAAY8aW5pdD4ABkxUZXN0OwAVTGphdmEvaW8vUHJpbnRTdHJlYW07ABJMamF2YS9sYW5nL09i"
205 "amVjdDsAEkxqYXZhL2xhbmcvU3RyaW5nOwASTGphdmEvbGFuZy9TeXN0ZW07AARUZXN0AAlUZXN0"
206 "LmphdmEAAVYAAlZMAANmb28AA291dAAHcHJpbnRsbgABAAcOAAMABw54AAAAAgAAgYAEnAIBCbQC"
207 "AAAADQAAAAAAAAABAAAAAAAAAAEAAAANAAAAcAAAAAIAAAAGAAAApAAAAAMAAAACAAAAvAAAAAQA"
208 "AAABAAAA1AAAAAUAAAAEAAAA3AAAAAYAAAABAAAA/AAAAAEgAAACAAAAHAEAAAEQAAABAAAAVAEA"
209 "AAIgAAANAAAAWgEAAAMgAAACAAAA6AEAAAAgAAABAAAA8wEAAAAQAAABAAAABAIAAA==";
210
211TEST_F(DexFileVerifierTest, GoodDex) {
212 ScratchFile tmp;
213 std::string error_msg;
214 std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kGoodTestDex, tmp.GetFilename().c_str(),
215 &error_msg));
216 ASSERT_TRUE(raw.get() != nullptr) << error_msg;
217}
218
Andreas Gampedf10b322014-06-11 21:46:05 -0700219TEST_F(DexFileVerifierTest, MethodId) {
Andreas Gampee6215c02015-08-31 18:54:38 -0700220 // Class idx error.
221 VerifyModification(
222 kGoodTestDex,
223 "method_id_class_idx",
224 [](DexFile* dex_file) {
225 DexFile::MethodId* method_id = const_cast<DexFile::MethodId*>(&dex_file->GetMethodId(0));
226 method_id->class_idx_ = 0xFF;
227 },
228 "could not find declaring class for direct method index 0");
229
230 // Proto idx error.
231 VerifyModification(
232 kGoodTestDex,
233 "method_id_proto_idx",
234 [](DexFile* dex_file) {
235 DexFile::MethodId* method_id = const_cast<DexFile::MethodId*>(&dex_file->GetMethodId(0));
236 method_id->proto_idx_ = 0xFF;
237 },
238 "inter_method_id_item proto_idx");
239
240 // Name idx error.
241 VerifyModification(
242 kGoodTestDex,
243 "method_id_name_idx",
244 [](DexFile* dex_file) {
245 DexFile::MethodId* method_id = const_cast<DexFile::MethodId*>(&dex_file->GetMethodId(0));
246 method_id->name_idx_ = 0xFF;
247 },
248 "String index not available for method flags verification");
249}
250
251// Method flags test class generated from the following smali code. The declared-synchronized
252// flags are there to enforce a 3-byte uLEB128 encoding so we don't have to relayout
253// the code, but we need to remove them before doing tests.
254//
255// .class public LMethodFlags;
256// .super Ljava/lang/Object;
257//
258// .method public static constructor <clinit>()V
259// .registers 1
260// return-void
261// .end method
262//
263// .method public constructor <init>()V
264// .registers 1
265// return-void
266// .end method
267//
268// .method private declared-synchronized foo()V
269// .registers 1
270// return-void
271// .end method
272//
273// .method public declared-synchronized bar()V
274// .registers 1
275// return-void
276// .end method
277
278static const char kMethodFlagsTestDex[] =
279 "ZGV4CjAzNQCyOQrJaDBwiIWv5MIuYKXhxlLLsQcx5SwgAgAAcAAAAHhWNBIAAAAAAAAAAJgBAAAH"
280 "AAAAcAAAAAMAAACMAAAAAQAAAJgAAAAAAAAAAAAAAAQAAACkAAAAAQAAAMQAAAA8AQAA5AAAAOQA"
281 "AADuAAAA9gAAAAUBAAAZAQAAHAEAACEBAAACAAAAAwAAAAQAAAAEAAAAAgAAAAAAAAAAAAAAAAAA"
282 "AAAAAAABAAAAAAAAAAUAAAAAAAAABgAAAAAAAAABAAAAAQAAAAAAAAD/////AAAAAHoBAAAAAAAA"
283 "CDxjbGluaXQ+AAY8aW5pdD4ADUxNZXRob2RGbGFnczsAEkxqYXZhL2xhbmcvT2JqZWN0OwABVgAD"
284 "YmFyAANmb28AAAAAAAAAAQAAAAAAAAAAAAAAAQAAAA4AAAABAAEAAAAAAAAAAAABAAAADgAAAAEA"
285 "AQAAAAAAAAAAAAEAAAAOAAAAAQABAAAAAAAAAAAAAQAAAA4AAAADAQCJgASsAgGBgATAAgKCgAjU"
286 "AgKBgAjoAgAACwAAAAAAAAABAAAAAAAAAAEAAAAHAAAAcAAAAAIAAAADAAAAjAAAAAMAAAABAAAA"
287 "mAAAAAUAAAAEAAAApAAAAAYAAAABAAAAxAAAAAIgAAAHAAAA5AAAAAMQAAABAAAAKAEAAAEgAAAE"
288 "AAAALAEAAAAgAAABAAAAegEAAAAQAAABAAAAmAEAAA==";
289
290// Find the method data for the first method with the given name (from class 0). Note: the pointer
291// is to the access flags, so that the caller doesn't have to handle the leb128-encoded method-index
292// delta.
293static const uint8_t* FindMethodData(const DexFile* dex_file, const char* name) {
294 const DexFile::ClassDef& class_def = dex_file->GetClassDef(0);
295 const uint8_t* class_data = dex_file->GetClassData(class_def);
296
297 ClassDataItemIterator it(*dex_file, class_data);
298
299 const uint8_t* trailing = class_data;
300 // Need to manually decode the four entries. DataPointer() doesn't work for this, as the first
301 // element has already been loaded into the iterator.
302 DecodeUnsignedLeb128(&trailing);
303 DecodeUnsignedLeb128(&trailing);
304 DecodeUnsignedLeb128(&trailing);
305 DecodeUnsignedLeb128(&trailing);
306
307 // Skip all fields.
308 while (it.HasNextStaticField() || it.HasNextInstanceField()) {
309 trailing = it.DataPointer();
310 it.Next();
Andreas Gampedf10b322014-06-11 21:46:05 -0700311 }
312
Andreas Gampee6215c02015-08-31 18:54:38 -0700313 while (it.HasNextDirectMethod() || it.HasNextVirtualMethod()) {
314 uint32_t method_index = it.GetMemberIndex();
315 uint32_t name_index = dex_file->GetMethodId(method_index).name_idx_;
316 const DexFile::StringId& string_id = dex_file->GetStringId(name_index);
317 const char* str = dex_file->GetStringData(string_id);
318 if (strcmp(name, str) == 0) {
319 DecodeUnsignedLeb128(&trailing);
320 return trailing;
321 }
322
323 trailing = it.DataPointer();
324 it.Next();
Andreas Gampedf10b322014-06-11 21:46:05 -0700325 }
326
Andreas Gampee6215c02015-08-31 18:54:38 -0700327 return nullptr;
328}
329
330// Set the method flags to the given value.
331static void SetMethodFlags(DexFile* dex_file, const char* method, uint32_t mask) {
332 uint8_t* method_flags_ptr = const_cast<uint8_t*>(FindMethodData(dex_file, method));
333 CHECK(method_flags_ptr != nullptr) << method;
334
335 // Unroll this, as we only have three bytes, anyways.
336 uint8_t base1 = static_cast<uint8_t>(mask & 0x7F);
337 *(method_flags_ptr++) = (base1 | 0x80);
338 mask >>= 7;
339
340 uint8_t base2 = static_cast<uint8_t>(mask & 0x7F);
341 *(method_flags_ptr++) = (base2 | 0x80);
342 mask >>= 7;
343
344 uint8_t base3 = static_cast<uint8_t>(mask & 0x7F);
345 *method_flags_ptr = base3;
346}
347
348static uint32_t GetMethodFlags(DexFile* dex_file, const char* method) {
349 const uint8_t* method_flags_ptr = const_cast<uint8_t*>(FindMethodData(dex_file, method));
350 CHECK(method_flags_ptr != nullptr) << method;
351 return DecodeUnsignedLeb128(&method_flags_ptr);
352}
353
354// Apply the given mask to method flags.
355static void ApplyMaskToMethodFlags(DexFile* dex_file, const char* method, uint32_t mask) {
356 uint32_t value = GetMethodFlags(dex_file, method);
357 value &= mask;
358 SetMethodFlags(dex_file, method, value);
359}
360
361// Apply the given mask to method flags.
362static void OrMaskToMethodFlags(DexFile* dex_file, const char* method, uint32_t mask) {
363 uint32_t value = GetMethodFlags(dex_file, method);
364 value |= mask;
365 SetMethodFlags(dex_file, method, value);
366}
367
368// Set code_off to 0 for the method.
369static void RemoveCode(DexFile* dex_file, const char* method) {
370 const uint8_t* ptr = FindMethodData(dex_file, method);
371 // Next is flags, pass.
372 DecodeUnsignedLeb128(&ptr);
373
374 // Figure out how many bytes the code_off is.
375 const uint8_t* tmp = ptr;
376 DecodeUnsignedLeb128(&tmp);
377 size_t bytes = tmp - ptr;
378
379 uint8_t* mod = const_cast<uint8_t*>(ptr);
380 for (size_t i = 1; i < bytes; ++i) {
381 *(mod++) = 0x80;
Andreas Gampedf10b322014-06-11 21:46:05 -0700382 }
Andreas Gampee6215c02015-08-31 18:54:38 -0700383 *mod = 0x00;
384}
385
386TEST_F(DexFileVerifierTest, MethodAccessFlagsBase) {
387 // Check that it's OK when the wrong declared-synchronized flag is removed from "foo."
388 VerifyModification(
389 kMethodFlagsTestDex,
390 "method_flags_ok",
391 [](DexFile* dex_file) {
392 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
393 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
394 },
395 nullptr);
396}
397
398TEST_F(DexFileVerifierTest, MethodAccessFlagsConstructors) {
399 // Make sure we still accept constructors without their flags.
400 VerifyModification(
401 kMethodFlagsTestDex,
402 "method_flags_missing_constructor_tag_ok",
403 [](DexFile* dex_file) {
404 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
405 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
406
407 ApplyMaskToMethodFlags(dex_file, "<init>", ~kAccConstructor);
408 ApplyMaskToMethodFlags(dex_file, "<clinit>", ~kAccConstructor);
409 },
410 nullptr);
411
412 constexpr const char* kConstructors[] = { "<clinit>", "<init>"};
413 for (size_t i = 0; i < 2; ++i) {
414 // Constructor with code marked native.
415 VerifyModification(
416 kMethodFlagsTestDex,
417 "method_flags_constructor_native",
418 [&](DexFile* dex_file) {
419 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
420 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
421
422 OrMaskToMethodFlags(dex_file, kConstructors[i], kAccNative);
423 },
424 "has code, but is marked native or abstract");
425 // Constructor with code marked abstract.
426 VerifyModification(
427 kMethodFlagsTestDex,
428 "method_flags_constructor_abstract",
429 [&](DexFile* dex_file) {
430 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
431 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
432
433 OrMaskToMethodFlags(dex_file, kConstructors[i], kAccAbstract);
434 },
435 "has code, but is marked native or abstract");
436 // Constructor as-is without code.
437 VerifyModification(
438 kMethodFlagsTestDex,
439 "method_flags_constructor_nocode",
440 [&](DexFile* dex_file) {
441 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
442 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
443
444 RemoveCode(dex_file, kConstructors[i]);
445 },
446 "has no code, but is not marked native or abstract");
447 // Constructor without code marked native.
448 VerifyModification(
449 kMethodFlagsTestDex,
450 "method_flags_constructor_native_nocode",
451 [&](DexFile* dex_file) {
452 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
453 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
454
455 OrMaskToMethodFlags(dex_file, kConstructors[i], kAccNative);
456 RemoveCode(dex_file, kConstructors[i]);
457 },
458 "must not be abstract or native");
459 // Constructor without code marked abstract.
460 VerifyModification(
461 kMethodFlagsTestDex,
462 "method_flags_constructor_abstract_nocode",
463 [&](DexFile* dex_file) {
464 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
465 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
466
467 OrMaskToMethodFlags(dex_file, kConstructors[i], kAccAbstract);
468 RemoveCode(dex_file, kConstructors[i]);
469 },
470 "must not be abstract or native");
471 }
472 // <init> may only have (modulo ignored):
473 // kAccPrivate | kAccProtected | kAccPublic | kAccStrict | kAccVarargs | kAccSynthetic
474 static constexpr uint32_t kInitAllowed[] = {
475 0,
476 kAccPrivate,
477 kAccProtected,
478 kAccPublic,
479 kAccStrict,
480 kAccVarargs,
481 kAccSynthetic
482 };
483 for (size_t i = 0; i < arraysize(kInitAllowed); ++i) {
484 VerifyModification(
485 kMethodFlagsTestDex,
486 "init_allowed_flags",
487 [&](DexFile* dex_file) {
488 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
489 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
490
491 ApplyMaskToMethodFlags(dex_file, "<init>", ~kAccPublic);
492 OrMaskToMethodFlags(dex_file, "<init>", kInitAllowed[i]);
493 },
494 nullptr);
495 }
496 // Only one of public-private-protected.
497 for (size_t i = 1; i < 8; ++i) {
498 if (POPCOUNT(i) < 2) {
499 continue;
500 }
501 // Technically the flags match, but just be defensive here.
502 uint32_t mask = ((i & 1) != 0 ? kAccPrivate : 0) |
503 ((i & 2) != 0 ? kAccProtected : 0) |
504 ((i & 4) != 0 ? kAccPublic : 0);
505 VerifyModification(
506 kMethodFlagsTestDex,
507 "init_one_of_ppp",
508 [&](DexFile* dex_file) {
509 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
510 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
511
512 ApplyMaskToMethodFlags(dex_file, "<init>", ~kAccPublic);
513 OrMaskToMethodFlags(dex_file, "<init>", mask);
514 },
515 "Method may have only one of public/protected/private");
516 }
517 // <init> doesn't allow
518 // kAccStatic | kAccFinal | kAccSynchronized | kAccBridge
519 // Need to handle static separately as it has its own error message.
520 VerifyModification(
521 kMethodFlagsTestDex,
522 "init_not_allowed_flags",
523 [&](DexFile* dex_file) {
524 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
525 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
526
527 ApplyMaskToMethodFlags(dex_file, "<init>", ~kAccPublic);
528 OrMaskToMethodFlags(dex_file, "<init>", kAccStatic);
529 },
Andreas Gampec9f0ba12016-02-09 09:21:04 -0800530 "Constructor 1(LMethodFlags;.<init>) is not flagged correctly wrt/ static");
Andreas Gampee6215c02015-08-31 18:54:38 -0700531 static constexpr uint32_t kInitNotAllowed[] = {
532 kAccFinal,
533 kAccSynchronized,
534 kAccBridge
535 };
536 for (size_t i = 0; i < arraysize(kInitNotAllowed); ++i) {
537 VerifyModification(
538 kMethodFlagsTestDex,
539 "init_not_allowed_flags",
540 [&](DexFile* dex_file) {
541 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
542 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
543
544 ApplyMaskToMethodFlags(dex_file, "<init>", ~kAccPublic);
545 OrMaskToMethodFlags(dex_file, "<init>", kInitNotAllowed[i]);
546 },
Andreas Gampec9f0ba12016-02-09 09:21:04 -0800547 "Constructor 1(LMethodFlags;.<init>) flagged inappropriately");
Andreas Gampee6215c02015-08-31 18:54:38 -0700548 }
549}
550
551TEST_F(DexFileVerifierTest, MethodAccessFlagsMethods) {
552 constexpr const char* kMethods[] = { "foo", "bar"};
553 for (size_t i = 0; i < arraysize(kMethods); ++i) {
554 // Make sure we reject non-constructors marked as constructors.
555 VerifyModification(
556 kMethodFlagsTestDex,
557 "method_flags_non_constructor",
558 [&](DexFile* dex_file) {
559 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
560 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
561
562 OrMaskToMethodFlags(dex_file, kMethods[i], kAccConstructor);
563 },
564 "is marked constructor, but doesn't match name");
565
566 VerifyModification(
567 kMethodFlagsTestDex,
568 "method_flags_native_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], kAccNative);
574 },
575 "has code, but is marked native or abstract");
576
577 VerifyModification(
578 kMethodFlagsTestDex,
579 "method_flags_abstract_with_code",
580 [&](DexFile* dex_file) {
581 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
582 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
583
584 OrMaskToMethodFlags(dex_file, kMethods[i], kAccAbstract);
585 },
586 "has code, but is marked native or abstract");
587
588 VerifyModification(
589 kMethodFlagsTestDex,
590 "method_flags_non_abstract_native_no_code",
591 [&](DexFile* dex_file) {
592 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
593 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
594
595 RemoveCode(dex_file, kMethods[i]);
596 },
597 "has no code, but is not marked native or abstract");
598
599 // Abstract methods may not have the following flags.
600 constexpr uint32_t kAbstractDisallowed[] = {
601 kAccPrivate,
602 kAccStatic,
603 kAccFinal,
604 kAccNative,
605 kAccStrict,
606 kAccSynchronized,
607 };
608 for (size_t j = 0; j < arraysize(kAbstractDisallowed); ++j) {
609 VerifyModification(
610 kMethodFlagsTestDex,
611 "method_flags_abstract_and_disallowed_no_code",
612 [&](DexFile* dex_file) {
613 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
614 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
615
616 RemoveCode(dex_file, kMethods[i]);
617
618 // Can't check private and static with foo, as it's in the virtual list and gives a
619 // different error.
620 if (((GetMethodFlags(dex_file, kMethods[i]) & kAccPublic) != 0) &&
621 ((kAbstractDisallowed[j] & (kAccPrivate | kAccStatic)) != 0)) {
622 // Use another breaking flag.
623 OrMaskToMethodFlags(dex_file, kMethods[i], kAccAbstract | kAccFinal);
624 } else {
625 OrMaskToMethodFlags(dex_file, kMethods[i], kAccAbstract | kAbstractDisallowed[j]);
626 }
627 },
628 "has disallowed access flags");
629 }
630
631 // Only one of public-private-protected.
632 for (size_t j = 1; j < 8; ++j) {
633 if (POPCOUNT(j) < 2) {
634 continue;
635 }
636 // Technically the flags match, but just be defensive here.
637 uint32_t mask = ((j & 1) != 0 ? kAccPrivate : 0) |
638 ((j & 2) != 0 ? kAccProtected : 0) |
639 ((j & 4) != 0 ? kAccPublic : 0);
640 VerifyModification(
641 kMethodFlagsTestDex,
642 "method_flags_one_of_ppp",
643 [&](DexFile* dex_file) {
644 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
645 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
646
647 ApplyMaskToMethodFlags(dex_file, kMethods[i], ~kAccPublic);
648 OrMaskToMethodFlags(dex_file, kMethods[i], mask);
649 },
650 "Method may have only one of public/protected/private");
651 }
652 }
653}
654
655TEST_F(DexFileVerifierTest, MethodAccessFlagsIgnoredOK) {
656 constexpr const char* kMethods[] = { "<clinit>", "<init>", "foo", "bar"};
657 for (size_t i = 0; i < arraysize(kMethods); ++i) {
658 // All interesting method flags, other flags are to be ignored.
659 constexpr uint32_t kAllMethodFlags =
660 kAccPublic |
661 kAccPrivate |
662 kAccProtected |
663 kAccStatic |
664 kAccFinal |
665 kAccSynchronized |
666 kAccBridge |
667 kAccVarargs |
668 kAccNative |
669 kAccAbstract |
670 kAccStrict |
671 kAccSynthetic;
672 constexpr uint32_t kIgnoredMask = ~kAllMethodFlags & 0xFFFF;
673 VerifyModification(
674 kMethodFlagsTestDex,
675 "method_flags_ignored",
676 [&](DexFile* dex_file) {
677 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
678 ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
679
680 OrMaskToMethodFlags(dex_file, kMethods[i], kIgnoredMask);
681 },
682 nullptr);
683 }
684}
685
686// Set of dex files for interface method tests. As it's not as easy to mutate method names, it's
687// just easier to break up bad cases.
688
Andreas Gampee6215c02015-08-31 18:54:38 -0700689// Standard interface. Use declared-synchronized again for 3B encoding.
690//
691// .class public interface LInterfaceMethodFlags;
692// .super Ljava/lang/Object;
693//
694// .method public static constructor <clinit>()V
695// .registers 1
696// return-void
697// .end method
698//
699// .method public abstract declared-synchronized foo()V
700// .end method
701static const char kMethodFlagsInterface[] =
702 "ZGV4CjAzNQCOM0odZ5bws1d9GSmumXaK5iE/7XxFpOm8AQAAcAAAAHhWNBIAAAAAAAAAADQBAAAF"
703 "AAAAcAAAAAMAAACEAAAAAQAAAJAAAAAAAAAAAAAAAAIAAACcAAAAAQAAAKwAAADwAAAAzAAAAMwA"
704 "AADWAAAA7gAAAAIBAAAFAQAAAQAAAAIAAAADAAAAAwAAAAIAAAAAAAAAAAAAAAAAAAAAAAAABAAA"
705 "AAAAAAABAgAAAQAAAAAAAAD/////AAAAACIBAAAAAAAACDxjbGluaXQ+ABZMSW50ZXJmYWNlTWV0"
706 "aG9kRmxhZ3M7ABJMamF2YS9sYW5nL09iamVjdDsAAVYAA2ZvbwAAAAAAAAABAAAAAAAAAAAAAAAB"
707 "AAAADgAAAAEBAImABJACAYGICAAAAAALAAAAAAAAAAEAAAAAAAAAAQAAAAUAAABwAAAAAgAAAAMA"
708 "AACEAAAAAwAAAAEAAACQAAAABQAAAAIAAACcAAAABgAAAAEAAACsAAAAAiAAAAUAAADMAAAAAxAA"
709 "AAEAAAAMAQAAASAAAAEAAAAQAQAAACAAAAEAAAAiAQAAABAAAAEAAAA0AQAA";
710
711// To simplify generation of interesting "sub-states" of src_value, allow a "simple" mask to apply
712// to a src_value, such that mask bit 0 applies to the lowest set bit in src_value, and so on.
713static uint32_t ApplyMaskShifted(uint32_t src_value, uint32_t mask) {
714 uint32_t result = 0;
715 uint32_t mask_index = 0;
716 while (src_value != 0) {
717 uint32_t index = CTZ(src_value);
718 if (((src_value & (1 << index)) != 0) &&
719 ((mask & (1 << mask_index)) != 0)) {
720 result |= (1 << index);
721 }
722 src_value &= ~(1 << index);
723 mask_index++;
724 }
725 return result;
726}
727
Andreas Gampe76ed99d2016-03-28 18:31:29 -0700728// Make the Dex file version 37.
729static void MakeDexVersion37(DexFile* dex_file) {
730 size_t offset = OFFSETOF_MEMBER(DexFile::Header, magic_) + 6;
731 CHECK_EQ(*(dex_file->Begin() + offset), '5');
732 *(const_cast<uint8_t*>(dex_file->Begin()) + offset) = '7';
733}
734
Andreas Gampee6215c02015-08-31 18:54:38 -0700735TEST_F(DexFileVerifierTest, MethodAccessFlagsInterfaces) {
Andreas Gampee6215c02015-08-31 18:54:38 -0700736 VerifyModification(
737 kMethodFlagsInterface,
738 "method_flags_interface_ok",
739 [](DexFile* dex_file) {
740 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
741 },
742 nullptr);
Andreas Gampe76ed99d2016-03-28 18:31:29 -0700743 VerifyModification(
744 kMethodFlagsInterface,
745 "method_flags_interface_ok37",
746 [](DexFile* dex_file) {
747 MakeDexVersion37(dex_file);
748 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
749 },
750 nullptr);
Andreas Gampee6215c02015-08-31 18:54:38 -0700751
752 VerifyModification(
753 kMethodFlagsInterface,
754 "method_flags_interface_non_public",
755 [](DexFile* dex_file) {
756 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
757
758 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccPublic);
759 },
Andreas Gampe76ed99d2016-03-28 18:31:29 -0700760 nullptr); // Should be allowed in older dex versions for backwards compatibility.
761 VerifyModification(
762 kMethodFlagsInterface,
763 "method_flags_interface_non_public",
764 [](DexFile* dex_file) {
765 MakeDexVersion37(dex_file);
766 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
767
768 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccPublic);
769 },
Alex Lightd7c10c22016-03-31 10:03:07 -0700770 "Interface virtual method 1(LInterfaceMethodFlags;.foo) is not public");
Andreas Gampe76ed99d2016-03-28 18:31:29 -0700771
Andreas Gampee6215c02015-08-31 18:54:38 -0700772 VerifyModification(
773 kMethodFlagsInterface,
774 "method_flags_interface_non_abstract",
775 [](DexFile* dex_file) {
776 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
777
778 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccAbstract);
779 },
Andreas Gampec9f0ba12016-02-09 09:21:04 -0800780 "Method 1(LInterfaceMethodFlags;.foo) has no code, but is not marked native or abstract");
Andreas Gampee6215c02015-08-31 18:54:38 -0700781
782 VerifyModification(
783 kMethodFlagsInterface,
784 "method_flags_interface_static",
785 [](DexFile* dex_file) {
786 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
787
788 OrMaskToMethodFlags(dex_file, "foo", kAccStatic);
789 },
Andreas Gampec9f0ba12016-02-09 09:21:04 -0800790 "Direct/virtual method 1(LInterfaceMethodFlags;.foo) not in expected list 0");
Andreas Gampee6215c02015-08-31 18:54:38 -0700791 VerifyModification(
792 kMethodFlagsInterface,
793 "method_flags_interface_private",
794 [](DexFile* dex_file) {
795 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
796
797 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccPublic);
798 OrMaskToMethodFlags(dex_file, "foo", kAccPrivate);
799 },
Andreas Gampec9f0ba12016-02-09 09:21:04 -0800800 "Direct/virtual method 1(LInterfaceMethodFlags;.foo) not in expected list 0");
Andreas Gampee6215c02015-08-31 18:54:38 -0700801
802 VerifyModification(
803 kMethodFlagsInterface,
804 "method_flags_interface_non_public",
805 [](DexFile* dex_file) {
806 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
807
808 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccPublic);
809 },
Andreas Gampe76ed99d2016-03-28 18:31:29 -0700810 nullptr); // Should be allowed in older dex versions for backwards compatibility.
811 VerifyModification(
812 kMethodFlagsInterface,
813 "method_flags_interface_non_public",
814 [](DexFile* dex_file) {
815 MakeDexVersion37(dex_file);
816 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
817
818 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccPublic);
819 },
Alex Lightd7c10c22016-03-31 10:03:07 -0700820 "Interface virtual method 1(LInterfaceMethodFlags;.foo) is not public");
Andreas Gampe76ed99d2016-03-28 18:31:29 -0700821
Andreas Gampee6215c02015-08-31 18:54:38 -0700822 VerifyModification(
823 kMethodFlagsInterface,
824 "method_flags_interface_protected",
825 [](DexFile* dex_file) {
826 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
827
828 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccPublic);
829 OrMaskToMethodFlags(dex_file, "foo", kAccProtected);
830 },
Andreas Gampe76ed99d2016-03-28 18:31:29 -0700831 nullptr); // Should be allowed in older dex versions for backwards compatibility.
832 VerifyModification(
833 kMethodFlagsInterface,
834 "method_flags_interface_protected",
835 [](DexFile* dex_file) {
836 MakeDexVersion37(dex_file);
837 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
838
839 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccPublic);
840 OrMaskToMethodFlags(dex_file, "foo", kAccProtected);
841 },
Alex Lightd7c10c22016-03-31 10:03:07 -0700842 "Interface virtual method 1(LInterfaceMethodFlags;.foo) is not public");
Andreas Gampee6215c02015-08-31 18:54:38 -0700843
844 constexpr uint32_t kAllMethodFlags =
845 kAccPublic |
846 kAccPrivate |
847 kAccProtected |
848 kAccStatic |
849 kAccFinal |
850 kAccSynchronized |
851 kAccBridge |
852 kAccVarargs |
853 kAccNative |
854 kAccAbstract |
855 kAccStrict |
856 kAccSynthetic;
857 constexpr uint32_t kInterfaceMethodFlags =
858 kAccPublic | kAccAbstract | kAccVarargs | kAccBridge | kAccSynthetic;
859 constexpr uint32_t kInterfaceDisallowed = kAllMethodFlags &
860 ~kInterfaceMethodFlags &
861 // Already tested, needed to be separate.
862 ~kAccStatic &
863 ~kAccPrivate &
864 ~kAccProtected;
865 static_assert(kInterfaceDisallowed != 0, "There should be disallowed flags.");
866
867 uint32_t bits = POPCOUNT(kInterfaceDisallowed);
868 for (uint32_t i = 1; i < (1u << bits); ++i) {
869 VerifyModification(
870 kMethodFlagsInterface,
871 "method_flags_interface_non_abstract",
872 [&](DexFile* dex_file) {
873 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
874
875 uint32_t mask = ApplyMaskShifted(kInterfaceDisallowed, i);
876 if ((mask & kAccProtected) != 0) {
877 mask &= ~kAccProtected;
878 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccPublic);
879 }
880 OrMaskToMethodFlags(dex_file, "foo", mask);
881 },
Andreas Gampec9f0ba12016-02-09 09:21:04 -0800882 "Abstract method 1(LInterfaceMethodFlags;.foo) has disallowed access flags");
Andreas Gampee6215c02015-08-31 18:54:38 -0700883 }
884}
885
886///////////////////////////////////////////////////////////////////
887
888// Field flags.
889
890// Find the method data for the first method with the given name (from class 0). Note: the pointer
891// is to the access flags, so that the caller doesn't have to handle the leb128-encoded method-index
892// delta.
893static const uint8_t* FindFieldData(const DexFile* dex_file, const char* name) {
894 const DexFile::ClassDef& class_def = dex_file->GetClassDef(0);
895 const uint8_t* class_data = dex_file->GetClassData(class_def);
896
897 ClassDataItemIterator it(*dex_file, class_data);
898
899 const uint8_t* trailing = class_data;
900 // Need to manually decode the four entries. DataPointer() doesn't work for this, as the first
901 // element has already been loaded into the iterator.
902 DecodeUnsignedLeb128(&trailing);
903 DecodeUnsignedLeb128(&trailing);
904 DecodeUnsignedLeb128(&trailing);
905 DecodeUnsignedLeb128(&trailing);
906
907 while (it.HasNextStaticField() || it.HasNextInstanceField()) {
908 uint32_t field_index = it.GetMemberIndex();
909 uint32_t name_index = dex_file->GetFieldId(field_index).name_idx_;
910 const DexFile::StringId& string_id = dex_file->GetStringId(name_index);
911 const char* str = dex_file->GetStringData(string_id);
912 if (strcmp(name, str) == 0) {
913 DecodeUnsignedLeb128(&trailing);
914 return trailing;
915 }
916
917 trailing = it.DataPointer();
918 it.Next();
919 }
920
921 return nullptr;
922}
923
924// Set the method flags to the given value.
925static void SetFieldFlags(DexFile* dex_file, const char* field, uint32_t mask) {
926 uint8_t* field_flags_ptr = const_cast<uint8_t*>(FindFieldData(dex_file, field));
927 CHECK(field_flags_ptr != nullptr) << field;
928
929 // Unroll this, as we only have three bytes, anyways.
930 uint8_t base1 = static_cast<uint8_t>(mask & 0x7F);
931 *(field_flags_ptr++) = (base1 | 0x80);
932 mask >>= 7;
933
934 uint8_t base2 = static_cast<uint8_t>(mask & 0x7F);
935 *(field_flags_ptr++) = (base2 | 0x80);
936 mask >>= 7;
937
938 uint8_t base3 = static_cast<uint8_t>(mask & 0x7F);
939 *field_flags_ptr = base3;
940}
941
942static uint32_t GetFieldFlags(DexFile* dex_file, const char* field) {
943 const uint8_t* field_flags_ptr = const_cast<uint8_t*>(FindFieldData(dex_file, field));
944 CHECK(field_flags_ptr != nullptr) << field;
945 return DecodeUnsignedLeb128(&field_flags_ptr);
946}
947
948// Apply the given mask to method flags.
949static void ApplyMaskToFieldFlags(DexFile* dex_file, const char* field, uint32_t mask) {
950 uint32_t value = GetFieldFlags(dex_file, field);
951 value &= mask;
952 SetFieldFlags(dex_file, field, value);
953}
954
955// Apply the given mask to method flags.
956static void OrMaskToFieldFlags(DexFile* dex_file, const char* field, uint32_t mask) {
957 uint32_t value = GetFieldFlags(dex_file, field);
958 value |= mask;
959 SetFieldFlags(dex_file, field, value);
960}
961
962// Standard class. Use declared-synchronized again for 3B encoding.
963//
964// .class public LFieldFlags;
965// .super Ljava/lang/Object;
966//
967// .field declared-synchronized public foo:I
968//
969// .field declared-synchronized public static bar:I
970
971static const char kFieldFlagsTestDex[] =
972 "ZGV4CjAzNQBtLw7hydbfv4TdXidZyzAB70W7w3vnYJRwAQAAcAAAAHhWNBIAAAAAAAAAAAABAAAF"
973 "AAAAcAAAAAMAAACEAAAAAAAAAAAAAAACAAAAkAAAAAAAAAAAAAAAAQAAAKAAAACwAAAAwAAAAMAA"
974 "AADDAAAA0QAAAOUAAADqAAAAAAAAAAEAAAACAAAAAQAAAAMAAAABAAAABAAAAAEAAAABAAAAAgAA"
975 "AAAAAAD/////AAAAAPQAAAAAAAAAAUkADExGaWVsZEZsYWdzOwASTGphdmEvbGFuZy9PYmplY3Q7"
976 "AANiYXIAA2ZvbwAAAAAAAAEBAAAAiYAIAYGACAkAAAAAAAAAAQAAAAAAAAABAAAABQAAAHAAAAAC"
977 "AAAAAwAAAIQAAAAEAAAAAgAAAJAAAAAGAAAAAQAAAKAAAAACIAAABQAAAMAAAAADEAAAAQAAAPAA"
978 "AAAAIAAAAQAAAPQAAAAAEAAAAQAAAAABAAA=";
979
980TEST_F(DexFileVerifierTest, FieldAccessFlagsBase) {
981 // Check that it's OK when the wrong declared-synchronized flag is removed from "foo."
982 VerifyModification(
983 kFieldFlagsTestDex,
984 "field_flags_ok",
985 [](DexFile* dex_file) {
986 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
987 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
988 },
989 nullptr);
990}
991
992TEST_F(DexFileVerifierTest, FieldAccessFlagsWrongList) {
993 // Mark the field so that it should appear in the opposite list (instance vs static).
994 VerifyModification(
995 kFieldFlagsTestDex,
996 "field_flags_wrong_list",
997 [](DexFile* dex_file) {
998 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
999 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
1000
1001 OrMaskToFieldFlags(dex_file, "foo", kAccStatic);
1002 },
1003 "Static/instance field not in expected list");
1004 VerifyModification(
1005 kFieldFlagsTestDex,
1006 "field_flags_wrong_list",
1007 [](DexFile* dex_file) {
1008 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1009 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
1010
1011 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccStatic);
1012 },
1013 "Static/instance field not in expected list");
1014}
1015
1016TEST_F(DexFileVerifierTest, FieldAccessFlagsPPP) {
1017 static const char* kFields[] = { "foo", "bar" };
1018 for (size_t i = 0; i < arraysize(kFields); ++i) {
1019 // Should be OK to remove public.
1020 VerifyModification(
1021 kFieldFlagsTestDex,
1022 "field_flags_non_public",
1023 [&](DexFile* dex_file) {
1024 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1025 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
1026
1027 ApplyMaskToFieldFlags(dex_file, kFields[i], ~kAccPublic);
1028 },
1029 nullptr);
1030 constexpr uint32_t kAccFlags = kAccPublic | kAccPrivate | kAccProtected;
1031 uint32_t bits = POPCOUNT(kAccFlags);
1032 for (uint32_t j = 1; j < (1u << bits); ++j) {
1033 if (POPCOUNT(j) < 2) {
1034 continue;
1035 }
1036 VerifyModification(
1037 kFieldFlagsTestDex,
1038 "field_flags_ppp",
1039 [&](DexFile* dex_file) {
1040 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1041 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
1042
1043 ApplyMaskToFieldFlags(dex_file, kFields[i], ~kAccPublic);
1044 uint32_t mask = ApplyMaskShifted(kAccFlags, j);
1045 OrMaskToFieldFlags(dex_file, kFields[i], mask);
1046 },
1047 "Field may have only one of public/protected/private");
1048 }
1049 }
1050}
1051
1052TEST_F(DexFileVerifierTest, FieldAccessFlagsIgnoredOK) {
1053 constexpr const char* kFields[] = { "foo", "bar"};
1054 for (size_t i = 0; i < arraysize(kFields); ++i) {
1055 // All interesting method flags, other flags are to be ignored.
1056 constexpr uint32_t kAllFieldFlags =
1057 kAccPublic |
1058 kAccPrivate |
1059 kAccProtected |
1060 kAccStatic |
1061 kAccFinal |
1062 kAccVolatile |
1063 kAccTransient |
1064 kAccSynthetic |
1065 kAccEnum;
1066 constexpr uint32_t kIgnoredMask = ~kAllFieldFlags & 0xFFFF;
1067 VerifyModification(
1068 kFieldFlagsTestDex,
1069 "field_flags_ignored",
1070 [&](DexFile* dex_file) {
1071 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1072 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
1073
1074 OrMaskToFieldFlags(dex_file, kFields[i], kIgnoredMask);
1075 },
1076 nullptr);
1077 }
1078}
1079
1080TEST_F(DexFileVerifierTest, FieldAccessFlagsVolatileFinal) {
1081 constexpr const char* kFields[] = { "foo", "bar"};
1082 for (size_t i = 0; i < arraysize(kFields); ++i) {
1083 VerifyModification(
1084 kFieldFlagsTestDex,
1085 "field_flags_final_and_volatile",
1086 [&](DexFile* dex_file) {
1087 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1088 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
1089
1090 OrMaskToFieldFlags(dex_file, kFields[i], kAccVolatile | kAccFinal);
1091 },
1092 "Fields may not be volatile and final");
1093 }
1094}
1095
1096// Standard interface. Needs to be separate from class as interfaces do not allow instance fields.
1097// Use declared-synchronized again for 3B encoding.
1098//
1099// .class public interface LInterfaceFieldFlags;
1100// .super Ljava/lang/Object;
1101//
1102// .field declared-synchronized public static final foo:I
1103
1104static const char kFieldFlagsInterfaceTestDex[] =
1105 "ZGV4CjAzNQCVMHfEimR1zZPk6hl6O9GPAYqkl3u0umFkAQAAcAAAAHhWNBIAAAAAAAAAAPQAAAAE"
1106 "AAAAcAAAAAMAAACAAAAAAAAAAAAAAAABAAAAjAAAAAAAAAAAAAAAAQAAAJQAAACwAAAAtAAAALQA"
1107 "AAC3AAAAzgAAAOIAAAAAAAAAAQAAAAIAAAABAAAAAwAAAAEAAAABAgAAAgAAAAAAAAD/////AAAA"
1108 "AOwAAAAAAAAAAUkAFUxJbnRlcmZhY2VGaWVsZEZsYWdzOwASTGphdmEvbGFuZy9PYmplY3Q7AANm"
1109 "b28AAAAAAAABAAAAAJmACAkAAAAAAAAAAQAAAAAAAAABAAAABAAAAHAAAAACAAAAAwAAAIAAAAAE"
1110 "AAAAAQAAAIwAAAAGAAAAAQAAAJQAAAACIAAABAAAALQAAAADEAAAAQAAAOgAAAAAIAAAAQAAAOwA"
1111 "AAAAEAAAAQAAAPQAAAA=";
1112
1113TEST_F(DexFileVerifierTest, FieldAccessFlagsInterface) {
1114 VerifyModification(
1115 kFieldFlagsInterfaceTestDex,
1116 "field_flags_interface",
1117 [](DexFile* dex_file) {
1118 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1119 },
1120 nullptr);
Andreas Gampe76ed99d2016-03-28 18:31:29 -07001121 VerifyModification(
1122 kFieldFlagsInterfaceTestDex,
1123 "field_flags_interface",
1124 [](DexFile* dex_file) {
1125 MakeDexVersion37(dex_file);
1126 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1127 },
1128 nullptr);
Andreas Gampee6215c02015-08-31 18:54:38 -07001129
1130 VerifyModification(
1131 kFieldFlagsInterfaceTestDex,
1132 "field_flags_interface_non_public",
1133 [](DexFile* dex_file) {
1134 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1135
1136 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccPublic);
1137 },
Andreas Gampe76ed99d2016-03-28 18:31:29 -07001138 nullptr); // Should be allowed in older dex versions for backwards compatibility.
1139 VerifyModification(
1140 kFieldFlagsInterfaceTestDex,
1141 "field_flags_interface_non_public",
1142 [](DexFile* dex_file) {
1143 MakeDexVersion37(dex_file);
1144 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1145
1146 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccPublic);
1147 },
Andreas Gampee6215c02015-08-31 18:54:38 -07001148 "Interface field is not public final static");
Andreas Gampe76ed99d2016-03-28 18:31:29 -07001149
Andreas Gampee6215c02015-08-31 18:54:38 -07001150 VerifyModification(
1151 kFieldFlagsInterfaceTestDex,
1152 "field_flags_interface_non_final",
1153 [](DexFile* dex_file) {
1154 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1155
1156 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccFinal);
1157 },
Andreas Gampe76ed99d2016-03-28 18:31:29 -07001158 nullptr); // Should be allowed in older dex versions for backwards compatibility.
1159 VerifyModification(
1160 kFieldFlagsInterfaceTestDex,
1161 "field_flags_interface_non_final",
1162 [](DexFile* dex_file) {
1163 MakeDexVersion37(dex_file);
1164 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1165
1166 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccFinal);
1167 },
Andreas Gampee6215c02015-08-31 18:54:38 -07001168 "Interface field is not public final static");
Andreas Gampe76ed99d2016-03-28 18:31:29 -07001169
Andreas Gampee6215c02015-08-31 18:54:38 -07001170 VerifyModification(
1171 kFieldFlagsInterfaceTestDex,
1172 "field_flags_interface_protected",
1173 [](DexFile* dex_file) {
1174 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1175
1176 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccPublic);
1177 OrMaskToFieldFlags(dex_file, "foo", kAccProtected);
1178 },
Andreas Gampe76ed99d2016-03-28 18:31:29 -07001179 nullptr); // Should be allowed in older dex versions for backwards compatibility.
1180 VerifyModification(
1181 kFieldFlagsInterfaceTestDex,
1182 "field_flags_interface_protected",
1183 [](DexFile* dex_file) {
1184 MakeDexVersion37(dex_file);
1185 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1186
1187 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccPublic);
1188 OrMaskToFieldFlags(dex_file, "foo", kAccProtected);
1189 },
Andreas Gampee6215c02015-08-31 18:54:38 -07001190 "Interface field is not public final static");
Andreas Gampe76ed99d2016-03-28 18:31:29 -07001191
Andreas Gampee6215c02015-08-31 18:54:38 -07001192 VerifyModification(
1193 kFieldFlagsInterfaceTestDex,
1194 "field_flags_interface_private",
1195 [](DexFile* dex_file) {
1196 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1197
1198 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccPublic);
1199 OrMaskToFieldFlags(dex_file, "foo", kAccPrivate);
1200 },
Andreas Gampe76ed99d2016-03-28 18:31:29 -07001201 nullptr); // Should be allowed in older dex versions for backwards compatibility.
1202 VerifyModification(
1203 kFieldFlagsInterfaceTestDex,
1204 "field_flags_interface_private",
1205 [](DexFile* dex_file) {
1206 MakeDexVersion37(dex_file);
1207 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1208
1209 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccPublic);
1210 OrMaskToFieldFlags(dex_file, "foo", kAccPrivate);
1211 },
Andreas Gampee6215c02015-08-31 18:54:38 -07001212 "Interface field is not public final static");
1213
1214 VerifyModification(
1215 kFieldFlagsInterfaceTestDex,
1216 "field_flags_interface_synthetic",
1217 [](DexFile* dex_file) {
1218 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1219
1220 OrMaskToFieldFlags(dex_file, "foo", kAccSynthetic);
1221 },
1222 nullptr);
1223
1224 constexpr uint32_t kAllFieldFlags =
1225 kAccPublic |
1226 kAccPrivate |
1227 kAccProtected |
1228 kAccStatic |
1229 kAccFinal |
1230 kAccVolatile |
1231 kAccTransient |
1232 kAccSynthetic |
1233 kAccEnum;
1234 constexpr uint32_t kInterfaceFieldFlags = kAccPublic | kAccStatic | kAccFinal | kAccSynthetic;
1235 constexpr uint32_t kInterfaceDisallowed = kAllFieldFlags &
1236 ~kInterfaceFieldFlags &
1237 ~kAccProtected &
1238 ~kAccPrivate;
1239 static_assert(kInterfaceDisallowed != 0, "There should be disallowed flags.");
1240
1241 uint32_t bits = POPCOUNT(kInterfaceDisallowed);
1242 for (uint32_t i = 1; i < (1u << bits); ++i) {
1243 VerifyModification(
1244 kFieldFlagsInterfaceTestDex,
1245 "field_flags_interface_disallowed",
1246 [&](DexFile* dex_file) {
1247 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1248
1249 uint32_t mask = ApplyMaskShifted(kInterfaceDisallowed, i);
1250 if ((mask & kAccProtected) != 0) {
1251 mask &= ~kAccProtected;
1252 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccPublic);
1253 }
1254 OrMaskToFieldFlags(dex_file, "foo", mask);
1255 },
Andreas Gampe76ed99d2016-03-28 18:31:29 -07001256 nullptr); // Should be allowed in older dex versions for backwards compatibility.
1257 VerifyModification(
1258 kFieldFlagsInterfaceTestDex,
1259 "field_flags_interface_disallowed",
1260 [&](DexFile* dex_file) {
1261 MakeDexVersion37(dex_file);
1262 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1263
1264 uint32_t mask = ApplyMaskShifted(kInterfaceDisallowed, i);
1265 if ((mask & kAccProtected) != 0) {
1266 mask &= ~kAccProtected;
1267 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccPublic);
1268 }
1269 OrMaskToFieldFlags(dex_file, "foo", mask);
1270 },
Andreas Gampee6215c02015-08-31 18:54:38 -07001271 "Interface field has disallowed flag");
1272 }
1273}
1274
1275// Standard bad interface. Needs to be separate from class as interfaces do not allow instance
1276// fields. Use declared-synchronized again for 3B encoding.
1277//
1278// .class public interface LInterfaceFieldFlags;
1279// .super Ljava/lang/Object;
1280//
1281// .field declared-synchronized public final foo:I
1282
1283static const char kFieldFlagsInterfaceBadTestDex[] =
1284 "ZGV4CjAzNQByMUnqYKHBkUpvvNp+9CnZ2VyDkKnRN6VkAQAAcAAAAHhWNBIAAAAAAAAAAPQAAAAE"
1285 "AAAAcAAAAAMAAACAAAAAAAAAAAAAAAABAAAAjAAAAAAAAAAAAAAAAQAAAJQAAACwAAAAtAAAALQA"
1286 "AAC3AAAAzgAAAOIAAAAAAAAAAQAAAAIAAAABAAAAAwAAAAEAAAABAgAAAgAAAAAAAAD/////AAAA"
1287 "AOwAAAAAAAAAAUkAFUxJbnRlcmZhY2VGaWVsZEZsYWdzOwASTGphdmEvbGFuZy9PYmplY3Q7AANm"
1288 "b28AAAAAAAAAAQAAAJGACAkAAAAAAAAAAQAAAAAAAAABAAAABAAAAHAAAAACAAAAAwAAAIAAAAAE"
1289 "AAAAAQAAAIwAAAAGAAAAAQAAAJQAAAACIAAABAAAALQAAAADEAAAAQAAAOgAAAAAIAAAAQAAAOwA"
1290 "AAAAEAAAAQAAAPQAAAA=";
1291
1292TEST_F(DexFileVerifierTest, FieldAccessFlagsInterfaceNonStatic) {
1293 VerifyModification(
1294 kFieldFlagsInterfaceBadTestDex,
1295 "field_flags_interface_non_static",
1296 [](DexFile* dex_file) {
1297 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1298 },
Andreas Gampe76ed99d2016-03-28 18:31:29 -07001299 nullptr); // Should be allowed in older dex versions for backwards compatibility.
1300 VerifyModification(
1301 kFieldFlagsInterfaceBadTestDex,
1302 "field_flags_interface_non_static",
1303 [](DexFile* dex_file) {
1304 MakeDexVersion37(dex_file);
1305 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1306 },
Andreas Gampee6215c02015-08-31 18:54:38 -07001307 "Interface field is not public final static");
Andreas Gampedf10b322014-06-11 21:46:05 -07001308}
1309
Logan Chiendd3208d2015-04-19 23:27:52 +08001310// Generated from:
1311//
1312// .class public LTest;
1313// .super Ljava/lang/Object;
1314// .source "Test.java"
1315//
1316// .method public constructor <init>()V
1317// .registers 1
1318//
1319// .prologue
1320// .line 1
1321// invoke-direct {p0}, Ljava/lang/Object;-><init>()V
1322//
1323// return-void
1324// .end method
1325//
1326// .method public static main()V
1327// .registers 2
1328//
1329// const-string v0, "a"
1330// const-string v0, "b"
1331// const-string v0, "c"
1332// const-string v0, "d"
1333// const-string v0, "e"
1334// const-string v0, "f"
1335// const-string v0, "g"
1336// const-string v0, "h"
1337// const-string v0, "i"
1338// const-string v0, "j"
1339// const-string v0, "k"
1340//
1341// .local v1, "local_var":Ljava/lang/String;
1342// const-string v1, "test"
1343// .end method
1344
1345static const char kDebugInfoTestDex[] =
1346 "ZGV4CjAzNQCHRkHix2eIMQgvLD/0VGrlllZLo0Rb6VyUAgAAcAAAAHhWNBIAAAAAAAAAAAwCAAAU"
1347 "AAAAcAAAAAQAAADAAAAAAQAAANAAAAAAAAAAAAAAAAMAAADcAAAAAQAAAPQAAACAAQAAFAEAABQB"
1348 "AAAcAQAAJAEAADgBAABMAQAAVwEAAFoBAABdAQAAYAEAAGMBAABmAQAAaQEAAGwBAABvAQAAcgEA"
1349 "AHUBAAB4AQAAewEAAIYBAACMAQAAAQAAAAIAAAADAAAABQAAAAUAAAADAAAAAAAAAAAAAAAAAAAA"
1350 "AAAAABIAAAABAAAAAAAAAAAAAAABAAAAAQAAAAAAAAAEAAAAAAAAAPwBAAAAAAAABjxpbml0PgAG"
1351 "TFRlc3Q7ABJMamF2YS9sYW5nL09iamVjdDsAEkxqYXZhL2xhbmcvU3RyaW5nOwAJVGVzdC5qYXZh"
1352 "AAFWAAFhAAFiAAFjAAFkAAFlAAFmAAFnAAFoAAFpAAFqAAFrAAlsb2NhbF92YXIABG1haW4ABHRl"
1353 "c3QAAAABAAcOAAAAARYDARIDAAAAAQABAAEAAACUAQAABAAAAHAQAgAAAA4AAgAAAAAAAACZAQAA"
1354 "GAAAABoABgAaAAcAGgAIABoACQAaAAoAGgALABoADAAaAA0AGgAOABoADwAaABAAGgETAAAAAgAA"
1355 "gYAEpAMBCbwDAAALAAAAAAAAAAEAAAAAAAAAAQAAABQAAABwAAAAAgAAAAQAAADAAAAAAwAAAAEA"
1356 "AADQAAAABQAAAAMAAADcAAAABgAAAAEAAAD0AAAAAiAAABQAAAAUAQAAAyAAAAIAAACUAQAAASAA"
1357 "AAIAAACkAQAAACAAAAEAAAD8AQAAABAAAAEAAAAMAgAA";
1358
1359TEST_F(DexFileVerifierTest, DebugInfoTypeIdxTest) {
1360 {
1361 // The input dex file should be good before modification.
1362 ScratchFile tmp;
1363 std::string error_msg;
1364 std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kDebugInfoTestDex,
1365 tmp.GetFilename().c_str(),
1366 &error_msg));
1367 ASSERT_TRUE(raw.get() != nullptr) << error_msg;
1368 }
1369
Andreas Gampee6215c02015-08-31 18:54:38 -07001370 // Modify the debug information entry.
1371 VerifyModification(
1372 kDebugInfoTestDex,
1373 "debug_start_type_idx",
1374 [](DexFile* dex_file) {
1375 *(const_cast<uint8_t*>(dex_file->Begin()) + 416) = 0x14U;
1376 },
1377 "DBG_START_LOCAL type_idx");
Logan Chiendd3208d2015-04-19 23:27:52 +08001378}
1379
Andreas Gampeb512c0e2016-02-19 19:45:34 -08001380TEST_F(DexFileVerifierTest, SectionAlignment) {
1381 {
1382 // The input dex file should be good before modification. Any file is fine, as long as it
1383 // uses all sections.
1384 ScratchFile tmp;
1385 std::string error_msg;
1386 std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kGoodTestDex,
1387 tmp.GetFilename().c_str(),
1388 &error_msg));
1389 ASSERT_TRUE(raw.get() != nullptr) << error_msg;
1390 }
1391
1392 // Modify all section offsets to be unaligned.
1393 constexpr size_t kSections = 7;
1394 for (size_t i = 0; i < kSections; ++i) {
1395 VerifyModification(
1396 kGoodTestDex,
1397 "section_align",
1398 [&](DexFile* dex_file) {
1399 DexFile::Header* header = const_cast<DexFile::Header*>(
1400 reinterpret_cast<const DexFile::Header*>(dex_file->Begin()));
1401 uint32_t* off_ptr;
1402 switch (i) {
1403 case 0:
1404 off_ptr = &header->map_off_;
1405 break;
1406 case 1:
1407 off_ptr = &header->string_ids_off_;
1408 break;
1409 case 2:
1410 off_ptr = &header->type_ids_off_;
1411 break;
1412 case 3:
1413 off_ptr = &header->proto_ids_off_;
1414 break;
1415 case 4:
1416 off_ptr = &header->field_ids_off_;
1417 break;
1418 case 5:
1419 off_ptr = &header->method_ids_off_;
1420 break;
1421 case 6:
1422 off_ptr = &header->class_defs_off_;
1423 break;
1424
1425 static_assert(kSections == 7, "kSections is wrong");
1426 default:
1427 LOG(FATAL) << "Unexpected section";
1428 UNREACHABLE();
1429 }
1430 ASSERT_TRUE(off_ptr != nullptr);
1431 ASSERT_NE(*off_ptr, 0U) << i; // Should already contain a value (in use).
1432 (*off_ptr)++; // Add one, which should misalign it (all the sections
1433 // above are aligned by 4).
1434 },
1435 "should be aligned by 4 for");
1436 }
1437}
1438
Andreas Gampedf10b322014-06-11 21:46:05 -07001439} // namespace art