• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     AutoPtr<ASTInterfaceType> interfaceType = ast_->GetInterfaceDef();
55     if (interfaceType == nullptr) {
56         return true;
57     }
58     if (!CheckIntfSaAstTypes() || !CheckIntfSaAstMethods()) {
59         return false;
60     }
61 
62     return true;
63 }
64 
CheckIntfSaAstTypes()65 bool IntfTypeChecker::CheckIntfSaAstTypes()
66 {
67     for (const auto &pair : ast_->GetTypes()) {
68         AutoPtr<ASTType> type = pair.second;
69         switch (type->GetTypeKind()) {
70             case TypeKind::TYPE_ASHMEM:
71             case TypeKind::TYPE_NATIVE_BUFFER:
72             case TypeKind::TYPE_POINTER:
73             case TypeKind::TYPE_SMQ:
74             Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf sa: type '%s' not support", __func__, __LINE__,
75                 pair.first.c_str()).c_str());
76                 return false;
77             default:
78                 break;
79         }
80     }
81     return true;
82 }
83 
CheckIntfSaAstMethods()84 bool IntfTypeChecker::CheckIntfSaAstMethods()
85 {
86     AutoPtr<ASTInterfaceType> interfaceType = ast_->GetInterfaceDef();
87     bool onewayInterface = (interfaceType->GetAttribute()->GetValue() == ASTAttr::ONEWAY);
88 
89     for (size_t i = 0; i < interfaceType->GetMethodNumber(); i++) {
90         AutoPtr<ASTMethod> method = interfaceType->GetMethod(i);
91         if (((method->GetAttribute()->GetValue()) &
92             (~(ASTAttr::ONEWAY | ASTAttr::CUSTOM_MSG_OPTION | ASTAttr::CACHEABLE | ASTAttr::IPCCODE |
93                 ASTAttr::IPC_IN_CAPACITY | ASTAttr::IPC_OUT_CAPACITY | ASTAttr::CALLBACK | ASTAttr::MACRO))) != 0) {
94             Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf sa: method attr support oneway, cacheable, "
95                 "ipccode, ipcincapacity, ipcoutcapacity, macrodef, macrondef", __func__, __LINE__).c_str());
96             return false;
97         }
98         if (method->GetAttribute()->HasValue(ASTAttr::CACHEABLE) &&
99             !method->GetAttribute()->HasValue(ASTAttr::ONEWAY)) {
100             auto ret = method->SetCacheableTime();
101             if (ret) {
102                 ast_->SetHasCacheableProxyMethods(true);
103             } else {
104                 Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf sa: method attr cacheable time invalid",
105                     __func__, __LINE__).c_str());
106                 return false;
107             }
108         }
109         if ((onewayInterface || method->GetAttribute()->GetValue() == ASTAttr::ONEWAY) &&
110             !method->GetReturnType()->IsVoidType()) {
111             Logger::E(TAG, StringHelper::Format(
112                 "[%s:%d] error:intf sa: method return type must be void in [oneway] interface or method", __func__,
113                 __LINE__).c_str());
114             return false;
115         }
116     }
117     return true;
118 }
119 
CheckIntfHdiAst()120 bool IntfTypeChecker::CheckIntfHdiAst()
121 {
122     if (ast_->GetPackageName().empty()) {
123         Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf hdi ast's package name is empty.", __func__,
124             __LINE__).c_str());
125         return false;
126     }
127 
128     if (!CheckIntfHdiAstFileType() || !CheckIntfHdiAstTypes()) {
129         return false;
130     }
131 
132     AutoPtr<ASTInterfaceType> interfaceType = ast_->GetInterfaceDef();
133     if (interfaceType == nullptr) {
134         return true;
135     }
136 
137     if (interfaceType->IsExternal()) {
138         Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf hdi: interface not support external", __func__,
139             __LINE__).c_str());
140         return false;
141     }
142 
143     for (size_t i = 0; i < interfaceType->GetMethodNumber(); i++) {
144         AutoPtr<ASTMethod> method = interfaceType->GetMethod(i);
145         for (size_t j = 0; j < method->GetParameterNumber(); j++) {
146             if (!CheckIntfHdiAstParam(method->GetParameter(j), i, j)) {
147                 return false;
148             }
149         }
150     }
151 
152     return true;
153 }
154 
CheckIntfHdiAstFileType()155 bool IntfTypeChecker::CheckIntfHdiAstFileType()
156 {
157     switch (ast_->GetASTFileType()) {
158         case ASTFileType::AST_IFACE:
159             return CheckInterfaceAst();
160         case ASTFileType::AST_ICALLBACK:
161             return CheckCallbackAst();
162         case ASTFileType::AST_SEQUENCEABLE:
163             Logger::E(TAG, StringHelper::Format("[%s:%d] error:it's impossible that ast is sequenceable.", __func__,
164                 __LINE__).c_str());
165             return false;
166         case ASTFileType::AST_TYPES:
167             if (ast_->GetInterfaceDef() != nullptr) {
168                 Logger::E(TAG, StringHelper::Format("[%s:%d] error:custom ast cannot has interface.", __func__,
169                     __LINE__).c_str());
170                 return false;
171             }
172             return true;
173         default:
174             return true;
175     }
176 }
177 
CheckIntfHdiAstTypes()178 bool IntfTypeChecker::CheckIntfHdiAstTypes()
179 {
180     for (const auto &pair : ast_->GetTypes()) {
181         AutoPtr<ASTType> type = pair.second;
182         if (type->GetTypeKind() == TypeKind::TYPE_CHAR) {
183             Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf hdi: type '%s' not support", __func__, __LINE__,
184                 pair.first.c_str()).c_str());
185             return false;
186         }
187     }
188     return true;
189 }
190 
CheckIntfHdiAstParam(AutoPtr<ASTParameter> param,size_t methodIdx,size_t paramIdx)191 bool IntfTypeChecker::CheckIntfHdiAstParam(AutoPtr<ASTParameter> param, size_t methodIdx, size_t paramIdx)
192 {
193     ASTParamAttr::ParamAttr paramAttr = param->GetAttribute();
194     if (paramAttr == ASTParamAttr::PARAM_INOUT) {
195         Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf hdi: method[%d] param[%d] attr not support "
196             "[inout] or [in, out]", __func__, __LINE__, methodIdx, paramIdx).c_str());
197         return false;
198     }
199 
200     AutoPtr<ASTType> paramType = param->GetType();
201     if (paramType != nullptr && paramType->IsInterfaceType()) {
202         AutoPtr<ASTInterfaceType> ifaceType = static_cast<ASTInterfaceType *>(paramType.Get());
203         if (ifaceType->IsCallback() && paramAttr != ASTParamAttr::PARAM_IN) {
204             Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf hdi: '%s' "
205                 "param of callback interface type must be 'in' attr", __func__, __LINE__,
206                 param->GetName().c_str()).c_str());
207             return false;
208         } else if (!ifaceType->IsCallback() && paramAttr != ASTParamAttr::PARAM_OUT) {
209             Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf hdi: '%s' param of interface "
210                 "type must be 'out' attr", __func__, __LINE__, param->GetName().c_str()).c_str());
211             return false;
212         }
213     }
214 
215     return true;
216 }
CheckInterfaceAst()217 bool IntfTypeChecker::CheckInterfaceAst()
218 {
219     AutoPtr<ASTInterfaceType> interface = ast_->GetInterfaceDef();
220     if (interface == nullptr) {
221         Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf hdi: ast's interface is empty.", __func__,
222             __LINE__).c_str());
223         return false;
224     }
225 
226     if (ast_->GetTypeDefinitionNumber() > 0) {
227         Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf hdi: interface ast cannot has custom types.", __func__,
228             __LINE__).c_str());
229         return false;
230     }
231 
232     if (interface->GetMethodNumber() == 0) {
233         Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf hdi: interface ast has no method.", __func__,
234             __LINE__).c_str());
235         return false;
236     }
237     return true;
238 }
239 
CheckCallbackAst()240 bool IntfTypeChecker::CheckCallbackAst()
241 {
242     AutoPtr<ASTInterfaceType> interface = ast_->GetInterfaceDef();
243     if (interface == nullptr) {
244         Logger::E(TAG, StringHelper::Format("[%s:%d] error:ast's interface is empty.", __func__, __LINE__).c_str());
245         return false;
246     }
247 
248     if (!interface->IsCallback()) {
249         Logger::E(TAG, StringHelper::Format("[%s:%d] error:ast is callback, but ast's interface is not callback.",
250             __func__, __LINE__).c_str());
251         return false;
252     }
253     return true;
254 }
255 
CheckIntfSmAst()256 bool IntfTypeChecker::CheckIntfSmAst()
257 {
258     if (ast_->GetPackageName().empty()) {
259         Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf sm ast's package name is empty.", __func__,
260             __LINE__).c_str());
261         return false;
262     }
263 
264     if (!CheckIntfSmAstFileType()) {
265         return false;
266     }
267 
268     for (const auto &pair : ast_->GetTypes()) {
269         AutoPtr<ASTType> type = pair.second;
270         if (type->GetTypeKind() == TypeKind::TYPE_CHAR) {
271         Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf sm: type '%s' not support", __func__, __LINE__,
272             pair.first.c_str()).c_str());
273             return false;
274         }
275     }
276 
277     return true;
278 }
279 
CheckIntfSmAstFileType()280 bool IntfTypeChecker::CheckIntfSmAstFileType()
281 {
282     switch (ast_->GetASTFileType()) {
283         case ASTFileType::AST_IFACE:
284             return CheckSmInterfaceAst();
285         case ASTFileType::AST_ICALLBACK:
286             return CheckCallbackAst();
287         case ASTFileType::AST_SEQUENCEABLE:
288             Logger::E(TAG, StringHelper::Format("[%s:%d] error:it's impossible that ast is sequenceable.",
289                 __func__, __LINE__).c_str());
290             return false;
291         case ASTFileType::AST_TYPES:
292             if (ast_->GetInterfaceDef() != nullptr) {
293                 Logger::E(TAG, StringHelper::Format("[%s:%d] error:custom ast cannot has interface.",
294                     __func__, __LINE__).c_str());
295                 return false;
296             }
297             return true;
298         default:
299             return true;
300     }
301 }
302 
CheckIntfSmAstTypes()303 bool IntfTypeChecker::CheckIntfSmAstTypes()
304 {
305     for (const auto &pair : ast_->GetTypes()) {
306         AutoPtr<ASTType> type = pair.second;
307         if (type->GetTypeKind() == TypeKind::TYPE_CHAR) {
308             Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf sm: type '%s' not support", __func__, __LINE__,
309                 pair.first.c_str()).c_str());
310             return false;
311         }
312     }
313     return true;
314 }
315 
CheckSmInterfaceAst()316 bool IntfTypeChecker::CheckSmInterfaceAst()
317 {
318     size_t index = 0;
319     for (size_t i = 0; i < ast_->GetInterfaceDefNumber(); i++) {
320         if (!ast_->GetInterfaceDef(i)->IsExternal()) {
321             index = i;
322             break;
323         }
324     }
325     AutoPtr<ASTInterfaceType> interface = ast_->GetInterfaceDef(index);
326     if (interface == nullptr) {
327         Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf sm: ast's interface is empty.", __func__,
328             __LINE__).c_str());
329         return false;
330     }
331 
332     if (ast_->GetTypeDefinitionNumber() > 0) {
333         Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf sm: interface ast cannot has custom types.", __func__,
334             __LINE__).c_str());
335         return false;
336     }
337 
338     if (interface->GetMethodNumber() == 0) {
339         Logger::E(TAG, StringHelper::Format("[%s:%d] error:intf sm: interface ast has no method.", __func__,
340             __LINE__).c_str());
341         return false;
342     }
343     return true;
344 }
345 
CheckBasicType(Token token)346 bool IntfTypeChecker::CheckBasicType(Token token)
347 {
348     switch (token.kind) {
349         case TokenType::VOID:
350         case TokenType::BOOLEAN:
351         case TokenType::BYTE:
352         case TokenType::SHORT:
353         case TokenType::INT:
354         case TokenType::LONG:
355         case TokenType::CSTRING:
356         case TokenType::STRING:
357         case TokenType::STRING16:
358         case TokenType::U16STRING:
359         case TokenType::FLOAT:
360         case TokenType::DOUBLE:
361         case TokenType::FD:
362         case TokenType::FDSAN:
363         case TokenType::ASHMEM:
364         case TokenType::NATIVE_BUFFER:
365         case TokenType::POINTER:
366         case TokenType::UNSIGNED:
367         case TokenType::CHAR:
368             return true;
369         default:
370             return false;
371     }
372 }
373 
CheckUserDefType(Token token)374 bool IntfTypeChecker::CheckUserDefType(Token token)
375 {
376     switch (token.kind) {
377         case TokenType::ENUM:
378         case TokenType::STRUCT:
379         case TokenType::UNION:
380         case TokenType::ID:
381         case TokenType::SEQ:
382             return true;
383         default:
384             return false;
385     }
386 }
387 
CheckMessageOption(std::string & messageOption)388 bool IntfTypeChecker::CheckMessageOption(std::string &messageOption)
389 {
390     std::string flags = "";
391     std::string waitTime = "";
392     std::string flags_replace = "flags=";
393     std::string waitTime_replace = "waitTime=";
394     std::vector<std::string> msgOpts = StringHelper::Split(messageOption, " and ");
395     if (msgOpts.size() == 1) {
396         if (StringHelper::StartWith(msgOpts[0], waitTime_replace)) {
397             Logger::E(TAG, StringHelper::Format("[%s:%d] error: customMsgOption should start with 'flags='.",
398                 __func__, __LINE__).c_str());
399             return false;
400         }
401         flags = StringHelper::Replace(msgOpts[0], flags_replace, "");
402         messageOption = flags;
403         return true;
404     }
405     if (msgOpts.size() > 1) {
406         if (StringHelper::StartWith(msgOpts[0], flags_replace)) {
407             flags = StringHelper::Replace(msgOpts[0], flags_replace, "");
408         } else if (StringHelper::StartWith(msgOpts[0], waitTime_replace)) {
409             waitTime = StringHelper::Replace(msgOpts[0], waitTime_replace, "");
410         } else {
411             Logger::E(TAG, StringHelper::Format(
412                 "[%s:%d] error: customMsgOption should start with 'flags=' or 'waitTime='.",
413                 __func__, __LINE__).c_str());
414             return false;
415         }
416 
417         if (StringHelper::StartWith(msgOpts[1], flags_replace) && !waitTime.empty()) {
418             flags = StringHelper::Replace(msgOpts[1], flags_replace, "");
419         } else if (StringHelper::StartWith(msgOpts[1], waitTime_replace) && !flags.empty()) {
420             waitTime = StringHelper::Replace(msgOpts[1], waitTime_replace, "");
421         } else {
422             Logger::E(TAG, StringHelper::Format(
423                 "[%s:%d] error: customMsgOption 'flags=' or 'waitTime=' should not empty.",
424                 __func__, __LINE__).c_str());
425             return false;
426         }
427         if (flags.empty() || waitTime.empty()) {
428             Logger::E(TAG, StringHelper::Format(
429                 "[%s:%d] error: customMsgOption 'flags=' or 'waitTime=' should not empty.",
430                 __func__, __LINE__).c_str());
431             return false;
432         }
433         messageOption = flags + ", " + waitTime;
434     }
435     return true;
436 }
437 
CheckSAPtrType(AutoPtr<ASTType> type)438 bool IntfTypeChecker::CheckSAPtrType(AutoPtr<ASTType> type)
439 {
440     Options &options = Options::GetInstance();
441     if (!(options.GetInterfaceType() == InterfaceType::SA && options.GetLanguage() == Language::CPP)) {
442         Logger::E(TAG, StringHelper::Format("[%s:%d] error: only --intf-type 'sa' and language 'cpp' support ptr",
443             __func__, __LINE__).c_str());
444         return false;
445     }
446     if ((type->GetTypeKind() == TypeKind::TYPE_SEQUENCEABLE && type->ToShortString() == "IRemoteObject") ||
447         type->GetTypeKind() == TypeKind::TYPE_INTERFACE) {
448         Logger::E(TAG, StringHelper::Format("[%s:%d] error: ptr not support 'IRemoteObject' and 'interface'",
449             __func__, __LINE__).c_str());
450         return false;
451     }
452     return true;
453 }
454 } // namespace Idl
455 } // namespace OHOS
456