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