blob: 272249c23a83849f969fc96165513a608caf86ce [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 },
530 "Constructor 1 is not flagged correctly wrt/ static");
531 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 },
547 "Constructor 1 flagged inappropriately");
548 }
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
689// Interface with an instance constructor.
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 constructor <init>()V
700// .registers 1
701// return-void
702// .end method
703static const char kMethodFlagsInterfaceWithInit[] =
704 "ZGV4CjAzNQDRNt+hZ6X3I+xe66iVlCW7h9I38HmN4SvUAQAAcAAAAHhWNBIAAAAAAAAAAEwBAAAF"
705 "AAAAcAAAAAMAAACEAAAAAQAAAJAAAAAAAAAAAAAAAAIAAACcAAAAAQAAAKwAAAAIAQAAzAAAAMwA"
706 "AADWAAAA3gAAAPYAAAAKAQAAAgAAAAMAAAAEAAAABAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAQAA"
707 "AAAAAAABAgAAAQAAAAAAAAD/////AAAAADoBAAAAAAAACDxjbGluaXQ+AAY8aW5pdD4AFkxJbnRl"
708 "cmZhY2VNZXRob2RGbGFnczsAEkxqYXZhL2xhbmcvT2JqZWN0OwABVgAAAAAAAAAAAQAAAAAAAAAA"
709 "AAAAAQAAAA4AAAABAAEAAAAAAAAAAAABAAAADgAAAAIAAImABJQCAYGABKgCAAALAAAAAAAAAAEA"
710 "AAAAAAAAAQAAAAUAAABwAAAAAgAAAAMAAACEAAAAAwAAAAEAAACQAAAABQAAAAIAAACcAAAABgAA"
711 "AAEAAACsAAAAAiAAAAUAAADMAAAAAxAAAAEAAAAQAQAAASAAAAIAAAAUAQAAACAAAAEAAAA6AQAA"
712 "ABAAAAEAAABMAQAA";
713
714// Standard interface. Use declared-synchronized again for 3B encoding.
715//
716// .class public interface LInterfaceMethodFlags;
717// .super Ljava/lang/Object;
718//
719// .method public static constructor <clinit>()V
720// .registers 1
721// return-void
722// .end method
723//
724// .method public abstract declared-synchronized foo()V
725// .end method
726static const char kMethodFlagsInterface[] =
727 "ZGV4CjAzNQCOM0odZ5bws1d9GSmumXaK5iE/7XxFpOm8AQAAcAAAAHhWNBIAAAAAAAAAADQBAAAF"
728 "AAAAcAAAAAMAAACEAAAAAQAAAJAAAAAAAAAAAAAAAAIAAACcAAAAAQAAAKwAAADwAAAAzAAAAMwA"
729 "AADWAAAA7gAAAAIBAAAFAQAAAQAAAAIAAAADAAAAAwAAAAIAAAAAAAAAAAAAAAAAAAAAAAAABAAA"
730 "AAAAAAABAgAAAQAAAAAAAAD/////AAAAACIBAAAAAAAACDxjbGluaXQ+ABZMSW50ZXJmYWNlTWV0"
731 "aG9kRmxhZ3M7ABJMamF2YS9sYW5nL09iamVjdDsAAVYAA2ZvbwAAAAAAAAABAAAAAAAAAAAAAAAB"
732 "AAAADgAAAAEBAImABJACAYGICAAAAAALAAAAAAAAAAEAAAAAAAAAAQAAAAUAAABwAAAAAgAAAAMA"
733 "AACEAAAAAwAAAAEAAACQAAAABQAAAAIAAACcAAAABgAAAAEAAACsAAAAAiAAAAUAAADMAAAAAxAA"
734 "AAEAAAAMAQAAASAAAAEAAAAQAQAAACAAAAEAAAAiAQAAABAAAAEAAAA0AQAA";
735
736// To simplify generation of interesting "sub-states" of src_value, allow a "simple" mask to apply
737// to a src_value, such that mask bit 0 applies to the lowest set bit in src_value, and so on.
738static uint32_t ApplyMaskShifted(uint32_t src_value, uint32_t mask) {
739 uint32_t result = 0;
740 uint32_t mask_index = 0;
741 while (src_value != 0) {
742 uint32_t index = CTZ(src_value);
743 if (((src_value & (1 << index)) != 0) &&
744 ((mask & (1 << mask_index)) != 0)) {
745 result |= (1 << index);
746 }
747 src_value &= ~(1 << index);
748 mask_index++;
749 }
750 return result;
751}
752
753TEST_F(DexFileVerifierTest, MethodAccessFlagsInterfaces) {
754 // Reject interface with <init>.
755 VerifyModification(
756 kMethodFlagsInterfaceWithInit,
757 "method_flags_interface_with_init",
758 [](DexFile* dex_file ATTRIBUTE_UNUSED) {},
759 "Non-clinit interface method 1 should not have code");
760
761 VerifyModification(
762 kMethodFlagsInterface,
763 "method_flags_interface_ok",
764 [](DexFile* dex_file) {
765 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
766 },
767 nullptr);
768
769 VerifyModification(
770 kMethodFlagsInterface,
771 "method_flags_interface_non_public",
772 [](DexFile* dex_file) {
773 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
774
775 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccPublic);
776 },
777 "Interface method 1 is not public and abstract");
778 VerifyModification(
779 kMethodFlagsInterface,
780 "method_flags_interface_non_abstract",
781 [](DexFile* dex_file) {
782 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
783
784 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccAbstract);
785 },
786 "Method 1 has no code, but is not marked native or abstract");
787
788 VerifyModification(
789 kMethodFlagsInterface,
790 "method_flags_interface_static",
791 [](DexFile* dex_file) {
792 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
793
794 OrMaskToMethodFlags(dex_file, "foo", kAccStatic);
795 },
796 "Direct/virtual method 1 not in expected list 0");
797 VerifyModification(
798 kMethodFlagsInterface,
799 "method_flags_interface_private",
800 [](DexFile* dex_file) {
801 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
802
803 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccPublic);
804 OrMaskToMethodFlags(dex_file, "foo", kAccPrivate);
805 },
806 "Direct/virtual method 1 not in expected list 0");
807
808 VerifyModification(
809 kMethodFlagsInterface,
810 "method_flags_interface_non_public",
811 [](DexFile* dex_file) {
812 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
813
814 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccPublic);
815 },
816 "Interface method 1 is not public and abstract");
817 VerifyModification(
818 kMethodFlagsInterface,
819 "method_flags_interface_protected",
820 [](DexFile* dex_file) {
821 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
822
823 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccPublic);
824 OrMaskToMethodFlags(dex_file, "foo", kAccProtected);
825 },
826 "Interface method 1 is not public and abstract");
827
828 constexpr uint32_t kAllMethodFlags =
829 kAccPublic |
830 kAccPrivate |
831 kAccProtected |
832 kAccStatic |
833 kAccFinal |
834 kAccSynchronized |
835 kAccBridge |
836 kAccVarargs |
837 kAccNative |
838 kAccAbstract |
839 kAccStrict |
840 kAccSynthetic;
841 constexpr uint32_t kInterfaceMethodFlags =
842 kAccPublic | kAccAbstract | kAccVarargs | kAccBridge | kAccSynthetic;
843 constexpr uint32_t kInterfaceDisallowed = kAllMethodFlags &
844 ~kInterfaceMethodFlags &
845 // Already tested, needed to be separate.
846 ~kAccStatic &
847 ~kAccPrivate &
848 ~kAccProtected;
849 static_assert(kInterfaceDisallowed != 0, "There should be disallowed flags.");
850
851 uint32_t bits = POPCOUNT(kInterfaceDisallowed);
852 for (uint32_t i = 1; i < (1u << bits); ++i) {
853 VerifyModification(
854 kMethodFlagsInterface,
855 "method_flags_interface_non_abstract",
856 [&](DexFile* dex_file) {
857 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
858
859 uint32_t mask = ApplyMaskShifted(kInterfaceDisallowed, i);
860 if ((mask & kAccProtected) != 0) {
861 mask &= ~kAccProtected;
862 ApplyMaskToMethodFlags(dex_file, "foo", ~kAccPublic);
863 }
864 OrMaskToMethodFlags(dex_file, "foo", mask);
865 },
866 "Abstract method 1 has disallowed access flags");
867 }
868}
869
870///////////////////////////////////////////////////////////////////
871
872// Field flags.
873
874// Find the method data for the first method with the given name (from class 0). Note: the pointer
875// is to the access flags, so that the caller doesn't have to handle the leb128-encoded method-index
876// delta.
877static const uint8_t* FindFieldData(const DexFile* dex_file, const char* name) {
878 const DexFile::ClassDef& class_def = dex_file->GetClassDef(0);
879 const uint8_t* class_data = dex_file->GetClassData(class_def);
880
881 ClassDataItemIterator it(*dex_file, class_data);
882
883 const uint8_t* trailing = class_data;
884 // Need to manually decode the four entries. DataPointer() doesn't work for this, as the first
885 // element has already been loaded into the iterator.
886 DecodeUnsignedLeb128(&trailing);
887 DecodeUnsignedLeb128(&trailing);
888 DecodeUnsignedLeb128(&trailing);
889 DecodeUnsignedLeb128(&trailing);
890
891 while (it.HasNextStaticField() || it.HasNextInstanceField()) {
892 uint32_t field_index = it.GetMemberIndex();
893 uint32_t name_index = dex_file->GetFieldId(field_index).name_idx_;
894 const DexFile::StringId& string_id = dex_file->GetStringId(name_index);
895 const char* str = dex_file->GetStringData(string_id);
896 if (strcmp(name, str) == 0) {
897 DecodeUnsignedLeb128(&trailing);
898 return trailing;
899 }
900
901 trailing = it.DataPointer();
902 it.Next();
903 }
904
905 return nullptr;
906}
907
908// Set the method flags to the given value.
909static void SetFieldFlags(DexFile* dex_file, const char* field, uint32_t mask) {
910 uint8_t* field_flags_ptr = const_cast<uint8_t*>(FindFieldData(dex_file, field));
911 CHECK(field_flags_ptr != nullptr) << field;
912
913 // Unroll this, as we only have three bytes, anyways.
914 uint8_t base1 = static_cast<uint8_t>(mask & 0x7F);
915 *(field_flags_ptr++) = (base1 | 0x80);
916 mask >>= 7;
917
918 uint8_t base2 = static_cast<uint8_t>(mask & 0x7F);
919 *(field_flags_ptr++) = (base2 | 0x80);
920 mask >>= 7;
921
922 uint8_t base3 = static_cast<uint8_t>(mask & 0x7F);
923 *field_flags_ptr = base3;
924}
925
926static uint32_t GetFieldFlags(DexFile* dex_file, const char* field) {
927 const uint8_t* field_flags_ptr = const_cast<uint8_t*>(FindFieldData(dex_file, field));
928 CHECK(field_flags_ptr != nullptr) << field;
929 return DecodeUnsignedLeb128(&field_flags_ptr);
930}
931
932// Apply the given mask to method flags.
933static void ApplyMaskToFieldFlags(DexFile* dex_file, const char* field, uint32_t mask) {
934 uint32_t value = GetFieldFlags(dex_file, field);
935 value &= mask;
936 SetFieldFlags(dex_file, field, value);
937}
938
939// Apply the given mask to method flags.
940static void OrMaskToFieldFlags(DexFile* dex_file, const char* field, uint32_t mask) {
941 uint32_t value = GetFieldFlags(dex_file, field);
942 value |= mask;
943 SetFieldFlags(dex_file, field, value);
944}
945
946// Standard class. Use declared-synchronized again for 3B encoding.
947//
948// .class public LFieldFlags;
949// .super Ljava/lang/Object;
950//
951// .field declared-synchronized public foo:I
952//
953// .field declared-synchronized public static bar:I
954
955static const char kFieldFlagsTestDex[] =
956 "ZGV4CjAzNQBtLw7hydbfv4TdXidZyzAB70W7w3vnYJRwAQAAcAAAAHhWNBIAAAAAAAAAAAABAAAF"
957 "AAAAcAAAAAMAAACEAAAAAAAAAAAAAAACAAAAkAAAAAAAAAAAAAAAAQAAAKAAAACwAAAAwAAAAMAA"
958 "AADDAAAA0QAAAOUAAADqAAAAAAAAAAEAAAACAAAAAQAAAAMAAAABAAAABAAAAAEAAAABAAAAAgAA"
959 "AAAAAAD/////AAAAAPQAAAAAAAAAAUkADExGaWVsZEZsYWdzOwASTGphdmEvbGFuZy9PYmplY3Q7"
960 "AANiYXIAA2ZvbwAAAAAAAAEBAAAAiYAIAYGACAkAAAAAAAAAAQAAAAAAAAABAAAABQAAAHAAAAAC"
961 "AAAAAwAAAIQAAAAEAAAAAgAAAJAAAAAGAAAAAQAAAKAAAAACIAAABQAAAMAAAAADEAAAAQAAAPAA"
962 "AAAAIAAAAQAAAPQAAAAAEAAAAQAAAAABAAA=";
963
964TEST_F(DexFileVerifierTest, FieldAccessFlagsBase) {
965 // Check that it's OK when the wrong declared-synchronized flag is removed from "foo."
966 VerifyModification(
967 kFieldFlagsTestDex,
968 "field_flags_ok",
969 [](DexFile* dex_file) {
970 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
971 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
972 },
973 nullptr);
974}
975
976TEST_F(DexFileVerifierTest, FieldAccessFlagsWrongList) {
977 // Mark the field so that it should appear in the opposite list (instance vs static).
978 VerifyModification(
979 kFieldFlagsTestDex,
980 "field_flags_wrong_list",
981 [](DexFile* dex_file) {
982 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
983 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
984
985 OrMaskToFieldFlags(dex_file, "foo", kAccStatic);
986 },
987 "Static/instance field not in expected list");
988 VerifyModification(
989 kFieldFlagsTestDex,
990 "field_flags_wrong_list",
991 [](DexFile* dex_file) {
992 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
993 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
994
995 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccStatic);
996 },
997 "Static/instance field not in expected list");
998}
999
1000TEST_F(DexFileVerifierTest, FieldAccessFlagsPPP) {
1001 static const char* kFields[] = { "foo", "bar" };
1002 for (size_t i = 0; i < arraysize(kFields); ++i) {
1003 // Should be OK to remove public.
1004 VerifyModification(
1005 kFieldFlagsTestDex,
1006 "field_flags_non_public",
1007 [&](DexFile* dex_file) {
1008 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1009 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
1010
1011 ApplyMaskToFieldFlags(dex_file, kFields[i], ~kAccPublic);
1012 },
1013 nullptr);
1014 constexpr uint32_t kAccFlags = kAccPublic | kAccPrivate | kAccProtected;
1015 uint32_t bits = POPCOUNT(kAccFlags);
1016 for (uint32_t j = 1; j < (1u << bits); ++j) {
1017 if (POPCOUNT(j) < 2) {
1018 continue;
1019 }
1020 VerifyModification(
1021 kFieldFlagsTestDex,
1022 "field_flags_ppp",
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 uint32_t mask = ApplyMaskShifted(kAccFlags, j);
1029 OrMaskToFieldFlags(dex_file, kFields[i], mask);
1030 },
1031 "Field may have only one of public/protected/private");
1032 }
1033 }
1034}
1035
1036TEST_F(DexFileVerifierTest, FieldAccessFlagsIgnoredOK) {
1037 constexpr const char* kFields[] = { "foo", "bar"};
1038 for (size_t i = 0; i < arraysize(kFields); ++i) {
1039 // All interesting method flags, other flags are to be ignored.
1040 constexpr uint32_t kAllFieldFlags =
1041 kAccPublic |
1042 kAccPrivate |
1043 kAccProtected |
1044 kAccStatic |
1045 kAccFinal |
1046 kAccVolatile |
1047 kAccTransient |
1048 kAccSynthetic |
1049 kAccEnum;
1050 constexpr uint32_t kIgnoredMask = ~kAllFieldFlags & 0xFFFF;
1051 VerifyModification(
1052 kFieldFlagsTestDex,
1053 "field_flags_ignored",
1054 [&](DexFile* dex_file) {
1055 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1056 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
1057
1058 OrMaskToFieldFlags(dex_file, kFields[i], kIgnoredMask);
1059 },
1060 nullptr);
1061 }
1062}
1063
1064TEST_F(DexFileVerifierTest, FieldAccessFlagsVolatileFinal) {
1065 constexpr const char* kFields[] = { "foo", "bar"};
1066 for (size_t i = 0; i < arraysize(kFields); ++i) {
1067 VerifyModification(
1068 kFieldFlagsTestDex,
1069 "field_flags_final_and_volatile",
1070 [&](DexFile* dex_file) {
1071 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1072 ApplyMaskToFieldFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
1073
1074 OrMaskToFieldFlags(dex_file, kFields[i], kAccVolatile | kAccFinal);
1075 },
1076 "Fields may not be volatile and final");
1077 }
1078}
1079
1080// Standard interface. Needs to be separate from class as interfaces do not allow instance fields.
1081// Use declared-synchronized again for 3B encoding.
1082//
1083// .class public interface LInterfaceFieldFlags;
1084// .super Ljava/lang/Object;
1085//
1086// .field declared-synchronized public static final foo:I
1087
1088static const char kFieldFlagsInterfaceTestDex[] =
1089 "ZGV4CjAzNQCVMHfEimR1zZPk6hl6O9GPAYqkl3u0umFkAQAAcAAAAHhWNBIAAAAAAAAAAPQAAAAE"
1090 "AAAAcAAAAAMAAACAAAAAAAAAAAAAAAABAAAAjAAAAAAAAAAAAAAAAQAAAJQAAACwAAAAtAAAALQA"
1091 "AAC3AAAAzgAAAOIAAAAAAAAAAQAAAAIAAAABAAAAAwAAAAEAAAABAgAAAgAAAAAAAAD/////AAAA"
1092 "AOwAAAAAAAAAAUkAFUxJbnRlcmZhY2VGaWVsZEZsYWdzOwASTGphdmEvbGFuZy9PYmplY3Q7AANm"
1093 "b28AAAAAAAABAAAAAJmACAkAAAAAAAAAAQAAAAAAAAABAAAABAAAAHAAAAACAAAAAwAAAIAAAAAE"
1094 "AAAAAQAAAIwAAAAGAAAAAQAAAJQAAAACIAAABAAAALQAAAADEAAAAQAAAOgAAAAAIAAAAQAAAOwA"
1095 "AAAAEAAAAQAAAPQAAAA=";
1096
1097TEST_F(DexFileVerifierTest, FieldAccessFlagsInterface) {
1098 VerifyModification(
1099 kFieldFlagsInterfaceTestDex,
1100 "field_flags_interface",
1101 [](DexFile* dex_file) {
1102 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1103 },
1104 nullptr);
1105
1106 VerifyModification(
1107 kFieldFlagsInterfaceTestDex,
1108 "field_flags_interface_non_public",
1109 [](DexFile* dex_file) {
1110 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1111
1112 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccPublic);
1113 },
1114 "Interface field is not public final static");
1115 VerifyModification(
1116 kFieldFlagsInterfaceTestDex,
1117 "field_flags_interface_non_final",
1118 [](DexFile* dex_file) {
1119 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1120
1121 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccFinal);
1122 },
1123 "Interface field is not public final static");
1124 VerifyModification(
1125 kFieldFlagsInterfaceTestDex,
1126 "field_flags_interface_protected",
1127 [](DexFile* dex_file) {
1128 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1129
1130 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccPublic);
1131 OrMaskToFieldFlags(dex_file, "foo", kAccProtected);
1132 },
1133 "Interface field is not public final static");
1134 VerifyModification(
1135 kFieldFlagsInterfaceTestDex,
1136 "field_flags_interface_private",
1137 [](DexFile* dex_file) {
1138 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1139
1140 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccPublic);
1141 OrMaskToFieldFlags(dex_file, "foo", kAccPrivate);
1142 },
1143 "Interface field is not public final static");
1144
1145 VerifyModification(
1146 kFieldFlagsInterfaceTestDex,
1147 "field_flags_interface_synthetic",
1148 [](DexFile* dex_file) {
1149 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1150
1151 OrMaskToFieldFlags(dex_file, "foo", kAccSynthetic);
1152 },
1153 nullptr);
1154
1155 constexpr uint32_t kAllFieldFlags =
1156 kAccPublic |
1157 kAccPrivate |
1158 kAccProtected |
1159 kAccStatic |
1160 kAccFinal |
1161 kAccVolatile |
1162 kAccTransient |
1163 kAccSynthetic |
1164 kAccEnum;
1165 constexpr uint32_t kInterfaceFieldFlags = kAccPublic | kAccStatic | kAccFinal | kAccSynthetic;
1166 constexpr uint32_t kInterfaceDisallowed = kAllFieldFlags &
1167 ~kInterfaceFieldFlags &
1168 ~kAccProtected &
1169 ~kAccPrivate;
1170 static_assert(kInterfaceDisallowed != 0, "There should be disallowed flags.");
1171
1172 uint32_t bits = POPCOUNT(kInterfaceDisallowed);
1173 for (uint32_t i = 1; i < (1u << bits); ++i) {
1174 VerifyModification(
1175 kFieldFlagsInterfaceTestDex,
1176 "field_flags_interface_disallowed",
1177 [&](DexFile* dex_file) {
1178 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1179
1180 uint32_t mask = ApplyMaskShifted(kInterfaceDisallowed, i);
1181 if ((mask & kAccProtected) != 0) {
1182 mask &= ~kAccProtected;
1183 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccPublic);
1184 }
1185 OrMaskToFieldFlags(dex_file, "foo", mask);
1186 },
1187 "Interface field has disallowed flag");
1188 }
1189}
1190
1191// Standard bad interface. Needs to be separate from class as interfaces do not allow instance
1192// fields. Use declared-synchronized again for 3B encoding.
1193//
1194// .class public interface LInterfaceFieldFlags;
1195// .super Ljava/lang/Object;
1196//
1197// .field declared-synchronized public final foo:I
1198
1199static const char kFieldFlagsInterfaceBadTestDex[] =
1200 "ZGV4CjAzNQByMUnqYKHBkUpvvNp+9CnZ2VyDkKnRN6VkAQAAcAAAAHhWNBIAAAAAAAAAAPQAAAAE"
1201 "AAAAcAAAAAMAAACAAAAAAAAAAAAAAAABAAAAjAAAAAAAAAAAAAAAAQAAAJQAAACwAAAAtAAAALQA"
1202 "AAC3AAAAzgAAAOIAAAAAAAAAAQAAAAIAAAABAAAAAwAAAAEAAAABAgAAAgAAAAAAAAD/////AAAA"
1203 "AOwAAAAAAAAAAUkAFUxJbnRlcmZhY2VGaWVsZEZsYWdzOwASTGphdmEvbGFuZy9PYmplY3Q7AANm"
1204 "b28AAAAAAAAAAQAAAJGACAkAAAAAAAAAAQAAAAAAAAABAAAABAAAAHAAAAACAAAAAwAAAIAAAAAE"
1205 "AAAAAQAAAIwAAAAGAAAAAQAAAJQAAAACIAAABAAAALQAAAADEAAAAQAAAOgAAAAAIAAAAQAAAOwA"
1206 "AAAAEAAAAQAAAPQAAAA=";
1207
1208TEST_F(DexFileVerifierTest, FieldAccessFlagsInterfaceNonStatic) {
1209 VerifyModification(
1210 kFieldFlagsInterfaceBadTestDex,
1211 "field_flags_interface_non_static",
1212 [](DexFile* dex_file) {
1213 ApplyMaskToFieldFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
1214 },
1215 "Interface field is not public final static");
Andreas Gampedf10b322014-06-11 21:46:05 -07001216}
1217
Logan Chiendd3208d2015-04-19 23:27:52 +08001218// Generated from:
1219//
1220// .class public LTest;
1221// .super Ljava/lang/Object;
1222// .source "Test.java"
1223//
1224// .method public constructor <init>()V
1225// .registers 1
1226//
1227// .prologue
1228// .line 1
1229// invoke-direct {p0}, Ljava/lang/Object;-><init>()V
1230//
1231// return-void
1232// .end method
1233//
1234// .method public static main()V
1235// .registers 2
1236//
1237// const-string v0, "a"
1238// const-string v0, "b"
1239// const-string v0, "c"
1240// const-string v0, "d"
1241// const-string v0, "e"
1242// const-string v0, "f"
1243// const-string v0, "g"
1244// const-string v0, "h"
1245// const-string v0, "i"
1246// const-string v0, "j"
1247// const-string v0, "k"
1248//
1249// .local v1, "local_var":Ljava/lang/String;
1250// const-string v1, "test"
1251// .end method
1252
1253static const char kDebugInfoTestDex[] =
1254 "ZGV4CjAzNQCHRkHix2eIMQgvLD/0VGrlllZLo0Rb6VyUAgAAcAAAAHhWNBIAAAAAAAAAAAwCAAAU"
1255 "AAAAcAAAAAQAAADAAAAAAQAAANAAAAAAAAAAAAAAAAMAAADcAAAAAQAAAPQAAACAAQAAFAEAABQB"
1256 "AAAcAQAAJAEAADgBAABMAQAAVwEAAFoBAABdAQAAYAEAAGMBAABmAQAAaQEAAGwBAABvAQAAcgEA"
1257 "AHUBAAB4AQAAewEAAIYBAACMAQAAAQAAAAIAAAADAAAABQAAAAUAAAADAAAAAAAAAAAAAAAAAAAA"
1258 "AAAAABIAAAABAAAAAAAAAAAAAAABAAAAAQAAAAAAAAAEAAAAAAAAAPwBAAAAAAAABjxpbml0PgAG"
1259 "TFRlc3Q7ABJMamF2YS9sYW5nL09iamVjdDsAEkxqYXZhL2xhbmcvU3RyaW5nOwAJVGVzdC5qYXZh"
1260 "AAFWAAFhAAFiAAFjAAFkAAFlAAFmAAFnAAFoAAFpAAFqAAFrAAlsb2NhbF92YXIABG1haW4ABHRl"
1261 "c3QAAAABAAcOAAAAARYDARIDAAAAAQABAAEAAACUAQAABAAAAHAQAgAAAA4AAgAAAAAAAACZAQAA"
1262 "GAAAABoABgAaAAcAGgAIABoACQAaAAoAGgALABoADAAaAA0AGgAOABoADwAaABAAGgETAAAAAgAA"
1263 "gYAEpAMBCbwDAAALAAAAAAAAAAEAAAAAAAAAAQAAABQAAABwAAAAAgAAAAQAAADAAAAAAwAAAAEA"
1264 "AADQAAAABQAAAAMAAADcAAAABgAAAAEAAAD0AAAAAiAAABQAAAAUAQAAAyAAAAIAAACUAQAAASAA"
1265 "AAIAAACkAQAAACAAAAEAAAD8AQAAABAAAAEAAAAMAgAA";
1266
1267TEST_F(DexFileVerifierTest, DebugInfoTypeIdxTest) {
1268 {
1269 // The input dex file should be good before modification.
1270 ScratchFile tmp;
1271 std::string error_msg;
1272 std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kDebugInfoTestDex,
1273 tmp.GetFilename().c_str(),
1274 &error_msg));
1275 ASSERT_TRUE(raw.get() != nullptr) << error_msg;
1276 }
1277
Andreas Gampee6215c02015-08-31 18:54:38 -07001278 // Modify the debug information entry.
1279 VerifyModification(
1280 kDebugInfoTestDex,
1281 "debug_start_type_idx",
1282 [](DexFile* dex_file) {
1283 *(const_cast<uint8_t*>(dex_file->Begin()) + 416) = 0x14U;
1284 },
1285 "DBG_START_LOCAL type_idx");
Logan Chiendd3208d2015-04-19 23:27:52 +08001286}
1287
Andreas Gampedf10b322014-06-11 21:46:05 -07001288} // namespace art