1 /*
2  * Copyright (C) 2019 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 "common_compiler_test.h"
18 
19 #include "aot_class_linker.h"
20 #include "base/casts.h"
21 #include "class_linker-inl.h"
22 #include "handle.h"
23 #include "handle_scope-inl.h"
24 #include "mirror/class_loader-inl.h"
25 #include "mirror/dex_cache.h"
26 #include "mirror/object-inl.h"
27 #include "runtime.h"
28 #include "scoped_thread_state_change-inl.h"
29 #include "thread-current-inl.h"
30 #include "well_known_classes.h"
31 
32 namespace art {
33 
34 class ModuleExclusionTest : public CommonCompilerTest {
35  public:
ModuleExclusionTest(const std::string & module)36   explicit ModuleExclusionTest(const std::string& module)
37       : CommonCompilerTest(),
38         module_(module) {}
39 
GetLibCoreModuleNames() const40   std::vector<std::string> GetLibCoreModuleNames() const override {
41     std::vector<std::string> modules = CommonCompilerTest::GetLibCoreModuleNames();
42     // Exclude `module_` from boot class path.
43     auto it = std::find(modules.begin(), modules.end(), module_);
44     if (it != modules.end()) {
45       modules.erase(it);
46     }
47     return modules;
48   }
49 
DoTest()50   void DoTest() {
51     Thread* self = Thread::Current();
52     ScopedObjectAccess soa(self);
53     StackHandleScope<2u> hs(self);
54     Runtime* runtime = Runtime::Current();
55     ASSERT_TRUE(runtime->IsAotCompiler());
56     ClassLinker* class_linker = runtime->GetClassLinker();
57     CHECK(loaded_dex_files_.empty());
58     Handle<mirror::ClassLoader> class_loader = hs.NewHandle(LoadModule(soa, class_linker));
59     MutableHandle<mirror::DexCache> dex_cache = hs.NewHandle<mirror::DexCache>(nullptr);
60     CHECK(!loaded_dex_files_.empty());
61 
62     // Verify that classes defined in the loaded dex files cannot be resolved.
63     for (const std::unique_ptr<const DexFile>& dex_file : loaded_dex_files_) {
64       dex_cache.Assign(class_linker->RegisterDexFile(*dex_file, class_loader.Get()));
65       for (size_t i = 0u, size = dex_file->NumClassDefs(); i != size; ++i) {
66         const dex::ClassDef& class_def = dex_file->GetClassDef(i);
67         ObjPtr<mirror::Class> resolved_type =
68             class_linker->ResolveType(class_def.class_idx_, dex_cache, class_loader);
69         ASSERT_TRUE(resolved_type == nullptr) << resolved_type->PrettyDescriptor();
70         ASSERT_TRUE(self->IsExceptionPending());
71         self->ClearException();
72       }
73     }
74   }
75 
76  protected:
SetUpRuntimeOptions(RuntimeOptions * options)77   void SetUpRuntimeOptions(RuntimeOptions* options) override {
78     CommonCompilerTest::SetUpRuntimeOptions(options);
79 
80     // Set up the image location to be used by StartDex2OatCommandLine().
81     // Using a prebuilt image also makes the test run faster.
82     options->push_back(std::make_pair("-Ximage:" + GetImageLocation(), nullptr));
83   }
84 
GetModuleFileName() const85   std::string GetModuleFileName() const {
86     std::vector<std::string> filename = GetLibCoreDexFileNames({ module_ });
87     CHECK_EQ(filename.size(), 1u);
88     return filename[0];
89   }
90 
91   // Load the module as an app, i.e. in a class loader other than the boot class loader.
LoadModule(ScopedObjectAccess & soa,ClassLinker * class_linker)92   ObjPtr<mirror::ClassLoader> LoadModule(ScopedObjectAccess& soa, ClassLinker* class_linker)
93       REQUIRES_SHARED(Locks::mutator_lock_) {
94     std::string filename = GetModuleFileName();
95     std::vector<std::unique_ptr<const DexFile>> dex_files = OpenDexFiles(filename.c_str());
96 
97     std::vector<const DexFile*> class_path;
98     CHECK_NE(0U, dex_files.size());
99     for (auto& dex_file : dex_files) {
100       class_path.push_back(dex_file.get());
101       loaded_dex_files_.push_back(std::move(dex_file));
102     }
103 
104     StackHandleScope<1u> hs(soa.Self());
105     Handle<mirror::Class> loader_class(hs.NewHandle(
106         soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_PathClassLoader)));
107     ScopedNullHandle<mirror::ClassLoader> parent_loader;
108     ScopedNullHandle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries;
109 
110     ObjPtr<mirror::ClassLoader> result = class_linker->CreateWellKnownClassLoader(
111         soa.Self(),
112         class_path,
113         loader_class,
114         parent_loader,
115         shared_libraries);
116 
117     // Verify that the result has the correct class.
118     CHECK_EQ(loader_class.Get(), result->GetClass());
119     // Verify that the parent is not null. The boot class loader will be set up as a
120     // proper BootClassLoader object.
121     ObjPtr<mirror::ClassLoader> actual_parent(result->GetParent());
122     CHECK(actual_parent != nullptr);
123     CHECK(class_linker->IsBootClassLoader(soa, actual_parent));
124 
125     return result;
126   }
127 
128   const std::string module_;
129 };
130 
131 class ConscryptExclusionTest : public ModuleExclusionTest {
132  public:
ConscryptExclusionTest()133   ConscryptExclusionTest() : ModuleExclusionTest("conscrypt") {}
134 };
135 
TEST_F(ConscryptExclusionTest,Test)136 TEST_F(ConscryptExclusionTest, Test) {
137   Runtime* runtime = Runtime::Current();
138   ASSERT_TRUE(runtime->IsAotCompiler());
139   AotClassLinker* aot_class_linker = down_cast<AotClassLinker*>(runtime->GetClassLinker());
140   const std::vector<std::string> package_list = {
141       // Reserved conscrypt packages (includes sub-packages under these paths).
142       "android.net.ssl",
143       "com.android.org.conscrypt",
144   };
145   bool list_applied = aot_class_linker->SetUpdatableBootClassPackages(package_list);
146   ASSERT_TRUE(list_applied);
147   DoTest();
148 
149   // Also test passing the list to dex2oat.
150   ScratchFile package_list_file;
151   for (const std::string& package : package_list) {
152     std::string data = package + '\n';
153     ASSERT_TRUE(package_list_file.GetFile()->WriteFully(data.data(), data.size()));
154   }
155   ASSERT_EQ(0, package_list_file.GetFile()->Flush());
156   ScratchDir scratch_dir;
157   std::string jar_name = GetModuleFileName();
158   std::string odex_name = scratch_dir.GetPath() + module_ + ".odex";
159   std::vector<std::string> argv;
160   std::string error_msg;
161   bool success = StartDex2OatCommandLine(&argv, &error_msg);
162   ASSERT_TRUE(success) << error_msg;
163   argv.insert(argv.end(), {
164       "--dex-file=" + jar_name,
165       "--dex-location=" + jar_name,
166       "--oat-file=" + odex_name,
167       "--compiler-filter=speed",
168       "--updatable-bcp-packages-file=" + package_list_file.GetFilename()
169   });
170   success = RunDex2Oat(argv, &error_msg);
171   ASSERT_TRUE(success) << error_msg;
172   // Load the odex file.
173   std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/ -1,
174                                                    odex_name.c_str(),
175                                                    odex_name.c_str(),
176                                                    /*executable=*/ false,
177                                                    /*low_4gb=*/ false,
178                                                    jar_name,
179                                                    &error_msg));
180   ASSERT_TRUE(odex_file != nullptr) << error_msg;
181   // Check that no classes have been resolved.
182   for (const OatDexFile* oat_dex_file : odex_file->GetOatDexFiles()) {
183     std::unique_ptr<const DexFile> dex_file = oat_dex_file->OpenDexFile(&error_msg);
184     ASSERT_TRUE(dex_file != nullptr);
185     for (size_t i = 0, num_class_defs = dex_file->NumClassDefs(); i != num_class_defs; ++i) {
186       ClassStatus status = oat_dex_file->GetOatClass(i).GetStatus();
187       ASSERT_FALSE(mirror::Class::IsErroneous(status));
188       ASSERT_LT(status, ClassStatus::kResolved);
189     }
190   }
191 }
192 
193 }  // namespace art
194