• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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