1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "verification.h"
17 #include "mir_nodes.h"
18 #include "class_hierarchy.h"
19 #include "utils.h"
20
21 namespace maple {
22 #ifdef NOT_USED
Run(MIRModule * module,ModuleResultMgr * mgr)23 AnalysisResult *DoVerification::Run(MIRModule *module, ModuleResultMgr *mgr)
24 {
25 LogInfo::MapleLogger() << "========== Starting Verify Module =====================" << '\n';
26 CHECK_FATAL(module != nullptr, "Module should be not null");
27 LogInfo::MapleLogger() << "Current module = " << module->GetFileName() << std::endl;
28
29 auto chaAnalysis = mgr->GetAnalysisResult(MoPhase_CHA, module);
30 if (chaAnalysis == nullptr) {
31 LogInfo::MapleLogger() << "Can't find class hierarchy result" << '\n';
32 return nullptr;
33 }
34 KlassHierarchy *klassHierarchy = static_cast<KlassHierarchy *>(chaAnalysis);
35
36 MemPool *memPool = NewMemPool();
37 auto *verifyResult = memPool->New<VerifyResult>(*module, *klassHierarchy, *memPool);
38 VerifyModule(*module, *verifyResult);
39 if (verifyResult->HasErrorNotDeferred()) {
40 LogInfo::MapleLogger() << "Warning: Verify MIR failed! " << '\n';
41 }
42
43 CheckExtendFinalClass(*verifyResult);
44 if (IsLazyBindingOrDecouple(*klassHierarchy)) {
45 DeferredCheckFinalClassAndMethod(*verifyResult);
46 }
47
48 auto *result = memPool->New<VerificationPhaseResult>(*memPool, *verifyResult);
49 mgr->AddResult(GetPhaseID(), *module, *result);
50 LogInfo::MapleLogger() << "========== Finished Verify Module =====================" << '\n';
51 return result;
52 }
53
CheckExtendFinalClass(VerifyResult & result) const54 void DoVerification::CheckExtendFinalClass(VerifyResult &result) const
55 {
56 const KlassHierarchy &klassHierarchy = result.GetKlassHierarchy();
57 std::stack<const Klass *> classesToMark;
58 for (auto klass : klassHierarchy.GetTopoSortedKlasses()) {
59 if (klass == nullptr || !klass->HasSubKlass()) {
60 continue;
61 }
62 const MIRStructType *mirStructType = klass->GetMIRStructType();
63 if ((mirStructType == nullptr) || (!mirStructType->IsMIRClassType()) ||
64 (!static_cast<const MIRClassType *>(mirStructType)->IsFinal())) {
65 continue;
66 }
67 classesToMark.push(klass);
68 while (!classesToMark.empty()) {
69 const auto &subKlasses = classesToMark.top()->GetSubKlasses();
70 classesToMark.pop();
71 for (auto subKlass : subKlasses) {
72 if (subKlass == nullptr) {
73 continue;
74 }
75 std::string errMsg =
76 "Class " + subKlass->GetKlassName() + " cannot inherit from final class " + klass->GetKlassName();
77 result.AddPragmaVerifyError(subKlass->GetKlassName(), std::move(errMsg));
78 if (subKlass->HasSubKlass()) {
79 classesToMark.push(subKlass);
80 }
81 }
82 }
83 }
84 }
85
IsLazyBindingOrDecouple(const KlassHierarchy & klassHierarchy) const86 bool DoVerification::IsLazyBindingOrDecouple(const KlassHierarchy &klassHierarchy) const
87 {
88 if (Options::buildApp != 0) {
89 return true;
90 }
91 const Klass *objectKlass = klassHierarchy.GetKlassFromLiteral(namemangler::kJavaLangObjectStr);
92 bool isLibCore = ((objectKlass != nullptr) && (objectKlass->GetMIRStructType()->IsLocal()));
93 return !isLibCore;
94 }
95
NeedRuntimeFinalCheck(const KlassHierarchy & klassHierarchy,const std::string & className) const96 bool DoVerification::NeedRuntimeFinalCheck(const KlassHierarchy &klassHierarchy, const std::string &className) const
97 {
98 const Klass *klass = klassHierarchy.GetKlassFromName(className);
99 if (klass == nullptr || klass->GetMIRStructType() == nullptr || !klass->HasSuperKlass()) {
100 return false;
101 }
102 return klass->GetMIRStructType()->IsLocal();
103 }
104
DeferredCheckFinalClassAndMethod(VerifyResult & result) const105 void DoVerification::DeferredCheckFinalClassAndMethod(VerifyResult &result) const
106 {
107 const auto &functionList = result.GetMIRModule().GetFunctionList();
108 std::set<std::string> classesAdded;
109 for (size_t index = 0; index < functionList.size(); ++index) {
110 result.SetCurrentFunction(index);
111 const auto &className = result.GetCurrentClassName();
112 if (classesAdded.find(className) != classesAdded.end()) {
113 continue;
114 }
115
116 if (!NeedRuntimeFinalCheck(result.GetKlassHierarchy(), className)) {
117 continue;
118 }
119 // do not extend final parent class
120 result.AddPragmaExtendFinalCheck(className);
121 // do not override final method
122 result.AddPragmaOverrideFinalCheck(className);
123 LogInfo::MapleLogger() << "Check Final class and method for class " << className << '\n';
124 (void)classesAdded.insert(className);
125 }
126 }
127
VerifyModule(MIRModule & module,VerifyResult & result) const128 void DoVerification::VerifyModule(MIRModule &module, VerifyResult &result) const
129 {
130 const auto &resultMap = result.GetResultMap();
131
132 // theModule is needed by verify() functions in mir_nodes.cpp
133 theMIRModule = &module;
134 const auto &functionList = result.GetMIRModule().GetFunctionList();
135 for (size_t index = 0; index < functionList.size(); ++index) {
136 result.SetCurrentFunction(index);
137 MIRFunction *currentFunction = functionList[index];
138 const BlockNode *block = currentFunction->GetBody();
139
140 // For verify() functions compatibility
141 theMIRModule->SetCurFunction(currentFunction);
142
143 if (block == nullptr) {
144 continue;
145 }
146 bool blockResult = block->Verify(result);
147
148 const auto &className = result.GetCurrentClassName();
149 auto iter = resultMap.find(className);
150 if (iter == resultMap.end()) {
151 result.SetClassCorrectness(className, blockResult);
152 } else {
153 result.SetClassCorrectness(className, iter->second && blockResult);
154 }
155 }
156 }
157 #endif
158
HasVerifyError(const std::vector<const VerifyPragmaInfo * > & pragmaInfoPtrVec) const159 bool VerifyResult::HasVerifyError(const std::vector<const VerifyPragmaInfo *> &pragmaInfoPtrVec) const
160 {
161 if (pragmaInfoPtrVec.empty()) {
162 return false;
163 }
164 return (utils::ToRef(pragmaInfoPtrVec.front()).IsVerifyError());
165 }
166
HasSamePragmaInfo(const std::vector<const VerifyPragmaInfo * > & pragmaInfoPtrVec,const VerifyPragmaInfo & verifyPragmaInfo) const167 bool VerifyResult::HasSamePragmaInfo(const std::vector<const VerifyPragmaInfo *> &pragmaInfoPtrVec,
168 const VerifyPragmaInfo &verifyPragmaInfo) const
169 {
170 for (auto &pragmaInfoPtr : pragmaInfoPtrVec) {
171 const VerifyPragmaInfo &pragmaInfoRef = utils::ToRef(pragmaInfoPtr);
172 if (!verifyPragmaInfo.IsEqualTo(pragmaInfoRef)) {
173 continue;
174 }
175 if (!verifyPragmaInfo.IsAssignableCheck()) {
176 return true;
177 }
178 if (static_cast<const AssignableCheckPragma &>(verifyPragmaInfo)
179 .IsEqualTo(static_cast<const AssignableCheckPragma &>(pragmaInfoRef))) {
180 return true;
181 }
182 }
183 return false;
184 }
185
AddPragmaVerifyError(const std::string & className,std::string errMsg)186 void VerifyResult::AddPragmaVerifyError(const std::string &className, std::string errMsg)
187 {
188 classesCorrectness[className] = false;
189 auto classIter = classesPragma.find(className);
190 if (classIter != classesPragma.end() && HasVerifyError(classIter->second)) {
191 return;
192 }
193 const VerifyPragmaInfo *verifyError = allocator.GetMemPool()->New<ThrowVerifyErrorPragma>(std::move(errMsg));
194 if (classIter == classesPragma.end()) {
195 classesPragma[className].push_back(verifyError);
196 return;
197 }
198 std::vector<const VerifyPragmaInfo *> &pragmaInfoPtrVec = classIter->second;
199 pragmaInfoPtrVec.clear();
200 pragmaInfoPtrVec.push_back(verifyError);
201 }
202
AddPragmaAssignableCheck(const std::string & className,std::string fromType,std::string toType)203 void VerifyResult::AddPragmaAssignableCheck(const std::string &className, std::string fromType, std::string toType)
204 {
205 classesCorrectness[className] = false;
206 auto classIter = classesPragma.find(className);
207 if (classIter != classesPragma.end() && HasVerifyError(classIter->second)) {
208 return;
209 }
210 const VerifyPragmaInfo *assignableCheck =
211 allocator.GetMemPool()->New<AssignableCheckPragma>(std::move(fromType), std::move(toType));
212 if (classIter == classesPragma.end()) {
213 classesPragma[className].push_back(assignableCheck);
214 return;
215 }
216 std::vector<const VerifyPragmaInfo *> &pragmaInfoPtrVec = classIter->second;
217 if (HasSamePragmaInfo(pragmaInfoPtrVec, *assignableCheck)) {
218 return;
219 }
220 pragmaInfoPtrVec.push_back(assignableCheck);
221 }
222
AddPragmaExtendFinalCheck(const std::string & className)223 void VerifyResult::AddPragmaExtendFinalCheck(const std::string &className)
224 {
225 classesCorrectness[className] = false;
226 auto classIter = classesPragma.find(className);
227 if (classIter != classesPragma.end() && HasVerifyError(classIter->second)) {
228 return;
229 }
230
231 const VerifyPragmaInfo *extendFinalCheck = allocator.GetMemPool()->New<ExtendFinalCheckPragma>();
232 if (classIter == classesPragma.end()) {
233 classesPragma[className].push_back(extendFinalCheck);
234 return;
235 }
236 std::vector<const VerifyPragmaInfo *> &pragmaInfoPtrVec = classIter->second;
237 if (HasSamePragmaInfo(pragmaInfoPtrVec, *extendFinalCheck)) {
238 return;
239 }
240 pragmaInfoPtrVec.push_back(extendFinalCheck);
241 }
242
AddPragmaOverrideFinalCheck(const std::string & className)243 void VerifyResult::AddPragmaOverrideFinalCheck(const std::string &className)
244 {
245 classesCorrectness[className] = false;
246 auto classIter = classesPragma.find(className);
247 if (classIter != classesPragma.end() && HasVerifyError(classIter->second)) {
248 return;
249 }
250
251 const VerifyPragmaInfo *overrideFinalCheck = allocator.GetMemPool()->New<OverrideFinalCheckPragma>();
252 if (classIter == classesPragma.end()) {
253 classesPragma[className].push_back(overrideFinalCheck);
254 return;
255 }
256 std::vector<const VerifyPragmaInfo *> &pragmaInfoPtrVec = classIter->second;
257 if (HasSamePragmaInfo(pragmaInfoPtrVec, *overrideFinalCheck)) {
258 return;
259 }
260 pragmaInfoPtrVec.push_back(overrideFinalCheck);
261 }
262 } // namespace maple
263