1 /*
2 * Copyright (c) 2024 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 "ast/ast_parameter.h"
17 #include "util/logger.h"
18 #include "util/string_builder.h"
19 #include "parser/intf_type_check.h"
20
21 namespace OHOS {
22 namespace Idl {
CheckIntegrity()23 bool IntfTypeChecker::CheckIntegrity()
24 {
25 if (ast_ == nullptr) {
26 Logger::E(TAG, StringHelper::Format("[%s:%d] error:ast is nullptr.", __func__, __LINE__).c_str());
27 return false;
28 }
29
30 if (ast_->GetName().empty()) {
31 Logger::E(TAG, StringHelper::Format("[%s:%d] error:ast's name is empty.", __func__, __LINE__).c_str());
32 return false;
33 }
34
35 InterfaceType interfaceType = Options::GetInstance().GetInterfaceType();
36 if (interfaceType == InterfaceType::SA) {
37 return CheckIntfSaAst();
38 } else if (interfaceType == InterfaceType::HDI) {
39 return CheckIntfHdiAst();
40 } else if (interfaceType == InterfaceType::SM ||
41 interfaceType == InterfaceType::SAM ||
42 interfaceType == InterfaceType::SAM_SM ||
43 interfaceType == InterfaceType::SAM_UDS ||
44 interfaceType == InterfaceType::SM_UDS) {
45 return CheckIntfSmAst();
46 }
47
48 Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf type is invalid.", __func__, __LINE__).c_str());
49 return false;
50 }
51
CheckIntfSaAst()52 bool IntfTypeChecker::CheckIntfSaAst()
53 {
54 if (!ast_->GetPackageName().empty()) {
55 Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf sa: package not support", __func__, __LINE__).c_str());
56 return false;
57 }
58
59 const auto &importMap = ast_->GetImports();
60 if (std::any_of(importMap.begin(), importMap.end(), [] (const std::pair<std::string, AutoPtr<AST>> &importPair) {
61 return importPair.second->GetASTFileType() != ASTFileType::AST_SEQUENCEABLE;
62 })) {
63 Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf sa: import not support", __func__, __LINE__).c_str());
64 return false;
65 }
66
67 bool definedIntf = false;
68 for (size_t i = 0; i < ast_->GetInterfaceDefNumber(); i++) {
69 if (!ast_->GetInterfaceDef(i)->IsExternal()) {
70 definedIntf = true;
71 break;
72 }
73 }
74
75 if (!definedIntf) {
76 Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf sa: interface is not defined.", __func__,
77 __LINE__).c_str());
78 return false;
79 }
80
81 ASTAttr::Attribute attr = ast_->GetInterfaceDef()->GetAttribute()->GetValue();
82 if ((attr != ASTAttr::NONE) && (attr != ASTAttr::ONEWAY)) {
83 Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf sa: interface attr only support [oneway]", __func__,
84 __LINE__).c_str());
85 return false;
86 }
87
88 if (!CheckIntfSaAstTypes() || !CheckIntfSaAstMethods()) {
89 return false;
90 }
91
92 return true;
93 }
94
CheckIntfSaAstTypes()95 bool IntfTypeChecker::CheckIntfSaAstTypes()
96 {
97 for (const auto &pair : ast_->GetTypes()) {
98 AutoPtr<ASTType> type = pair.second;
99 switch (type->GetTypeKind()) {
100 case TypeKind::TYPE_FILEDESCRIPTOR:
101 case TypeKind::TYPE_ASHMEM:
102 case TypeKind::TYPE_NATIVE_BUFFER:
103 case TypeKind::TYPE_POINTER:
104 case TypeKind::TYPE_SMQ:
105 case TypeKind::TYPE_ENUM:
106 case TypeKind::TYPE_STRUCT:
107 case TypeKind::TYPE_UNION:
108 case TypeKind::TYPE_UCHAR:
109 case TypeKind::TYPE_USHORT:
110 case TypeKind::TYPE_UINT:
111 case TypeKind::TYPE_ULONG:
112 Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf sa: type '%s' not support", __func__, __LINE__,
113 pair.first.c_str()).c_str());
114 return false;
115 default:
116 break;
117 }
118 }
119 return true;
120 }
121
CheckIntfSaAstMethods()122 bool IntfTypeChecker::CheckIntfSaAstMethods()
123 {
124 AutoPtr<ASTInterfaceType> interfaceType = ast_->GetInterfaceDef();
125 bool onewayInterface = (interfaceType->GetAttribute()->GetValue() == ASTAttr::ONEWAY);
126
127 for (size_t i = 0; i < interfaceType->GetMethodNumber(); i++) {
128 AutoPtr<ASTMethod> method = interfaceType->GetMethod(i);
129 if (((method->GetAttribute()->GetValue()) & (~(ASTAttr::ONEWAY | ASTAttr::CACHEABLE))) != 0) {
130 Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf sa: method attr support oneway or cacheable",
131 __func__, __LINE__).c_str());
132 return false;
133 }
134 if (method->GetAttribute()->HasValue(ASTAttr::CACHEABLE) &&
135 !method->GetAttribute()->HasValue(ASTAttr::ONEWAY)) {
136 auto ret = method->SetCacheableTime();
137 if (ret) {
138 ast_->SetHasCacheableProxyMethods(true);
139 } else {
140 Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf sa: method attr cacheable time invalid",
141 __func__, __LINE__).c_str());
142 return false;
143 }
144 }
145 if ((onewayInterface || method->GetAttribute()->GetValue() == ASTAttr::ONEWAY) &&
146 !method->GetReturnType()->IsVoidType()) {
147 Logger::E(TAG, StringHelper::Format(
148 "[%s:%d] error:intf sa: method return type must be void in [oneway] interface or method", __func__,
149 __LINE__).c_str());
150 return false;
151 }
152 }
153 return true;
154 }
155
CheckIntfHdiAst()156 bool IntfTypeChecker::CheckIntfHdiAst()
157 {
158 if (ast_->GetPackageName().empty()) {
159 Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf hdi ast's package name is empty.", __func__,
160 __LINE__).c_str());
161 return false;
162 }
163
164 if (!CheckIntfHdiAstFileType() || !CheckIntfHdiAstTypes()) {
165 return false;
166 }
167
168 AutoPtr<ASTInterfaceType> interfaceType = ast_->GetInterfaceDef();
169 if (interfaceType == nullptr) {
170 return true;
171 }
172
173 if (interfaceType->IsExternal()) {
174 Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf hdi: interface not support external", __func__,
175 __LINE__).c_str());
176 return false;
177 }
178
179 for (size_t i = 0; i < interfaceType->GetMethodNumber(); i++) {
180 AutoPtr<ASTMethod> method = interfaceType->GetMethod(i);
181 for (size_t j = 0; j < method->GetParameterNumber(); j++) {
182 if (!CheckIntfHdiAstParam(method->GetParameter(j), i, j)) {
183 return false;
184 }
185 }
186 }
187
188 return true;
189 }
190
CheckIntfHdiAstFileType()191 bool IntfTypeChecker::CheckIntfHdiAstFileType()
192 {
193 switch (ast_->GetASTFileType()) {
194 case ASTFileType::AST_IFACE:
195 return CheckInterfaceAst();
196 case ASTFileType::AST_ICALLBACK:
197 return CheckCallbackAst();
198 case ASTFileType::AST_SEQUENCEABLE:
199 Logger::E(TAG, StringHelper::Format("[%s:%d] error:it's impossible that ast is sequenceable.", __func__,
200 __LINE__).c_str());
201 return false;
202 case ASTFileType::AST_TYPES:
203 if (ast_->GetInterfaceDef() != nullptr) {
204 Logger::E(TAG, StringHelper::Format("[%s:%d] error:custom ast cannot has interface.", __func__,
205 __LINE__).c_str());
206 return false;
207 }
208 return true;
209 default:
210 return true;
211 }
212 }
213
CheckIntfHdiAstTypes()214 bool IntfTypeChecker::CheckIntfHdiAstTypes()
215 {
216 for (const auto &pair : ast_->GetTypes()) {
217 AutoPtr<ASTType> type = pair.second;
218 if (type->GetTypeKind() == TypeKind::TYPE_CHAR) {
219 Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf hdi: type '%s' not support", __func__, __LINE__,
220 pair.first.c_str()).c_str());
221 return false;
222 }
223 }
224 return true;
225 }
226
CheckIntfHdiAstParam(AutoPtr<ASTParameter> param,size_t methodIdx,size_t paramIdx)227 bool IntfTypeChecker::CheckIntfHdiAstParam(AutoPtr<ASTParameter> param, size_t methodIdx, size_t paramIdx)
228 {
229 ASTParamAttr::ParamAttr paramAttr = param->GetAttribute();
230 if (paramAttr == ASTParamAttr::PARAM_INOUT) {
231 Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf hdi: method[%d] param[%d] attr not support "
232 "[inout] or [in, out]", __func__, __LINE__, methodIdx, paramIdx).c_str());
233 return false;
234 }
235
236 AutoPtr<ASTType> paramType = param->GetType();
237 if (paramType != nullptr && paramType->IsInterfaceType()) {
238 AutoPtr<ASTInterfaceType> ifaceType = dynamic_cast<ASTInterfaceType *>(paramType.Get());
239 if (ifaceType->IsCallback() && paramAttr != ASTParamAttr::PARAM_IN) {
240 Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf hdi: '%s' "
241 "param of callback interface type must be 'in' attr", __func__, __LINE__,
242 param->GetName().c_str()).c_str());
243 return false;
244 } else if (!ifaceType->IsCallback() && paramAttr != ASTParamAttr::PARAM_OUT) {
245 Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf hdi: '%s' param of interface "
246 "type must be 'out' attr", __func__, __LINE__, param->GetName().c_str()).c_str());
247 return false;
248 }
249 }
250
251 return true;
252 }
CheckInterfaceAst()253 bool IntfTypeChecker::CheckInterfaceAst()
254 {
255 AutoPtr<ASTInterfaceType> interface = ast_->GetInterfaceDef();
256 if (interface == nullptr) {
257 Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf hdi: ast's interface is empty.", __func__,
258 __LINE__).c_str());
259 return false;
260 }
261
262 if (ast_->GetTypeDefinitionNumber() > 0) {
263 Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf hdi: interface ast cannot has custom types.", __func__,
264 __LINE__).c_str());
265 return false;
266 }
267
268 if (interface->GetMethodNumber() == 0) {
269 Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf hdi: interface ast has no method.", __func__,
270 __LINE__).c_str());
271 return false;
272 }
273 return true;
274 }
275
CheckCallbackAst()276 bool IntfTypeChecker::CheckCallbackAst()
277 {
278 AutoPtr<ASTInterfaceType> interface = ast_->GetInterfaceDef();
279 if (interface == nullptr) {
280 Logger::E(TAG, StringHelper::Format("[%s:%d] error:ast's interface is empty.", __func__, __LINE__).c_str());
281 return false;
282 }
283
284 if (!interface->IsCallback()) {
285 Logger::E(TAG, StringHelper::Format("[%s:%d] error:ast is callback, but ast's interface is not callback.",
286 __func__, __LINE__).c_str());
287 return false;
288 }
289 return true;
290 }
291
CheckIntfSmAst()292 bool IntfTypeChecker::CheckIntfSmAst()
293 {
294 if (ast_->GetPackageName().empty()) {
295 Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf sm ast's package name is empty.", __func__,
296 __LINE__).c_str());
297 return false;
298 }
299
300 if (!CheckIntfSmAstFileType()) {
301 return false;
302 }
303
304 for (const auto &pair : ast_->GetTypes()) {
305 AutoPtr<ASTType> type = pair.second;
306 if (type->GetTypeKind() == TypeKind::TYPE_CHAR) {
307 Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf sm: type '%s' not support", __func__, __LINE__,
308 pair.first.c_str()).c_str());
309 return false;
310 }
311 }
312
313 return true;
314 }
315
CheckIntfSmAstFileType()316 bool IntfTypeChecker::CheckIntfSmAstFileType()
317 {
318 switch (ast_->GetASTFileType()) {
319 case ASTFileType::AST_IFACE:
320 return CheckSmInterfaceAst();
321 case ASTFileType::AST_ICALLBACK:
322 return CheckCallbackAst();
323 case ASTFileType::AST_SEQUENCEABLE:
324 Logger::E(TAG, StringHelper::Format("[%s:%d] error:it's impossible that ast is sequenceable.",
325 __func__, __LINE__).c_str());
326 return false;
327 case ASTFileType::AST_TYPES:
328 if (ast_->GetInterfaceDef() != nullptr) {
329 Logger::E(TAG, StringHelper::Format("[%s:%d] error:custom ast cannot has interface.",
330 __func__, __LINE__).c_str());
331 return false;
332 }
333 return true;
334 default:
335 return true;
336 }
337 }
338
CheckIntfSmAstTypes()339 bool IntfTypeChecker::CheckIntfSmAstTypes()
340 {
341 for (const auto &pair : ast_->GetTypes()) {
342 AutoPtr<ASTType> type = pair.second;
343 if (type->GetTypeKind() == TypeKind::TYPE_CHAR) {
344 Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf sm: type '%s' not support", __func__, __LINE__,
345 pair.first.c_str()).c_str());
346 return false;
347 }
348 }
349 return true;
350 }
351
CheckSmInterfaceAst()352 bool IntfTypeChecker::CheckSmInterfaceAst()
353 {
354 size_t index = 0;
355 for (size_t i = 0; i < ast_->GetInterfaceDefNumber(); i++) {
356 if (!ast_->GetInterfaceDef(i)->IsExternal()) {
357 index = i;
358 break;
359 }
360 }
361 AutoPtr<ASTInterfaceType> interface = ast_->GetInterfaceDef(index);
362 if (interface == nullptr) {
363 Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf sm: ast's interface is empty.", __func__,
364 __LINE__).c_str());
365 return false;
366 }
367
368 if (ast_->GetTypeDefinitionNumber() > 0) {
369 Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf sm: interface ast cannot has custom types.", __func__,
370 __LINE__).c_str());
371 return false;
372 }
373
374 if (interface->GetMethodNumber() == 0) {
375 Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf sm: interface ast has no method.", __func__,
376 __LINE__).c_str());
377 return false;
378 }
379 return true;
380 }
381 } // namespace Idl
382 } // namespace OHOS
383