• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 "hiappevent_verify.h"
17 
18 #include <cctype>
19 #include <iterator>
20 #include <regex>
21 #include <unordered_set>
22 
23 #include "hiappevent_base.h"
24 #include "hiappevent_config.h"
25 #include "hilog/log.h"
26 
27 using namespace OHOS::HiviewDFX::ErrorCode;
28 
29 namespace OHOS {
30 namespace HiviewDFX {
31 namespace {
32 static constexpr HiLogLabel LABEL = { LOG_CORE, HIAPPEVENT_DOMAIN, "HiAppEvent_verify" };
33 
34 constexpr size_t MAX_LEN_OF_WATCHER = 32;
35 constexpr size_t MAX_LEN_OF_DOMAIN = 16;
36 static constexpr int MAX_LENGTH_OF_EVENT_NAME = 48;
37 static constexpr int MAX_LENGTH_OF_PARAM_NAME = 16;
38 static constexpr unsigned int MAX_NUM_OF_PARAMS = 32;
39 static constexpr size_t MAX_LENGTH_OF_STR_PARAM = 8 * 1024;
40 static constexpr size_t MAX_LENGTH_OF_SPECIAL_STR_PARAM = 1024 * 1024;
41 static constexpr int MAX_SIZE_OF_LIST_PARAM = 100;
42 static constexpr int MAX_LENGTH_OF_USER_INFO_NAME = 256;
43 static constexpr int MAX_LENGTH_OF_USER_ID_VALUE = 256;
44 static constexpr int MAX_LENGTH_OF_USER_PROPERTY_VALUE = 1024;
45 static constexpr int MAX_LENGTH_OF_PROCESSOR_NAME = 256;
46 static constexpr int MAX_LEN_OF_BATCH_REPORT = 1000;
47 
IsValidName(const std::string & name,size_t maxSize)48 bool IsValidName(const std::string& name, size_t maxSize)
49 {
50     if (name.empty() || name.length() > maxSize) {
51         return false;
52     }
53     // start char is [$a-zA-Z]
54     if (!isalpha(name[0]) && name[0] != '$') {
55         return false;
56     }
57     // end char is [a-zA-Z0-9]
58     if (name.length() > 1 && (!isalnum(name.back()))) {
59         return false;
60     }
61     // middle char is [a-zA-Z0-9_]
62     for (size_t i = 1; i < name.length() - 1; ++i) {
63         if (!isalnum(name[i]) && name[i] != '_') {
64             return false;
65         }
66     }
67     return true;
68 }
69 
CheckParamName(const std::string & paramName)70 bool CheckParamName(const std::string& paramName)
71 {
72     return IsValidName(paramName, MAX_LENGTH_OF_PARAM_NAME);
73 }
74 
EscapeStringValue(std::string & value)75 void EscapeStringValue(std::string &value)
76 {
77     std::string escapeValue;
78     for (auto it = value.begin(); it != value.end(); it++) {
79         switch (*it) {
80             case '\\':
81                 escapeValue.append("\\\\");
82                 break;
83             case '\"':
84                 escapeValue.append("\\\"");
85                 break;
86             case '\b':
87                 escapeValue.append("\\b");
88                 break;
89             case '\f':
90                 escapeValue.append("\\f");
91                 break;
92             case '\n':
93                 escapeValue.append("\\n");
94                 break;
95             case '\r':
96                 escapeValue.append("\\r");
97                 break;
98             case '\t':
99                 escapeValue.append("\\t");
100                 break;
101             default:
102                 escapeValue.push_back(*it);
103                 break;
104         }
105     }
106     value = escapeValue;
107 }
108 
CheckStrParamLength(std::string & strParamValue,size_t maxLen=MAX_LENGTH_OF_STR_PARAM)109 bool CheckStrParamLength(std::string& strParamValue, size_t maxLen = MAX_LENGTH_OF_STR_PARAM)
110 {
111     if (strParamValue.empty()) {
112         HiLog::Warn(LABEL, "str param value is empty.");
113         return true;
114     }
115 
116     if (strParamValue.length() > maxLen) {
117         return false;
118     }
119 
120     EscapeStringValue(strParamValue);
121     return true;
122 }
123 
CheckListValueSize(AppEventParamType type,AppEventParamValue::ValueUnion & vu)124 bool CheckListValueSize(AppEventParamType type, AppEventParamValue::ValueUnion& vu)
125 {
126     if (type == AppEventParamType::BVECTOR && vu.bs_.size() > MAX_SIZE_OF_LIST_PARAM) {
127         vu.bs_.resize(MAX_SIZE_OF_LIST_PARAM);
128     } else if (type == AppEventParamType::CVECTOR && vu.cs_.size() > MAX_SIZE_OF_LIST_PARAM) {
129         vu.cs_.resize(MAX_SIZE_OF_LIST_PARAM);
130     } else if (type == AppEventParamType::SHVECTOR && vu.shs_.size() > MAX_SIZE_OF_LIST_PARAM) {
131         vu.shs_.resize(MAX_SIZE_OF_LIST_PARAM);
132     } else if (type == AppEventParamType::IVECTOR && vu.is_.size() > MAX_SIZE_OF_LIST_PARAM) {
133         vu.is_.resize(MAX_SIZE_OF_LIST_PARAM);
134     } else if (type == AppEventParamType::LLVECTOR && vu.lls_.size() > MAX_SIZE_OF_LIST_PARAM) {
135         vu.lls_.resize(MAX_SIZE_OF_LIST_PARAM);
136     } else if (type == AppEventParamType::FVECTOR && vu.fs_.size() > MAX_SIZE_OF_LIST_PARAM) {
137         vu.fs_.resize(MAX_SIZE_OF_LIST_PARAM);
138     } else if (type == AppEventParamType::DVECTOR && vu.ds_.size() > MAX_SIZE_OF_LIST_PARAM) {
139         vu.ds_.resize(MAX_SIZE_OF_LIST_PARAM);
140     } else if (type == AppEventParamType::STRVECTOR && vu.strs_.size() > MAX_SIZE_OF_LIST_PARAM) {
141         vu.strs_.resize(MAX_SIZE_OF_LIST_PARAM);
142     } else {
143         return true;
144     }
145 
146     return false;
147 }
148 
CheckStringLengthOfList(std::vector<std::string> & strs)149 bool CheckStringLengthOfList(std::vector<std::string>& strs)
150 {
151     if (strs.empty()) {
152         return true;
153     }
154 
155     for (auto it = strs.begin(); it != strs.end(); it++) {
156         if (!CheckStrParamLength(*it)) {
157             return false;
158         }
159     }
160 
161     return true;
162 }
163 
CheckParamsNum(std::list<AppEventParam> & baseParams)164 bool CheckParamsNum(std::list<AppEventParam>& baseParams)
165 {
166     if (baseParams.size() == 0) {
167         return true;
168     }
169 
170     auto listSize = baseParams.size();
171     if (listSize > MAX_NUM_OF_PARAMS) {
172         auto delStartPtr = baseParams.begin();
173         std::advance(delStartPtr, MAX_NUM_OF_PARAMS);
174         baseParams.erase(delStartPtr, baseParams.end());
175         return false;
176     }
177 
178     return true;
179 }
180 
VerifyAppEventParam(AppEventParam & param,std::unordered_set<std::string> & paramNames,int & verifyRes)181 bool VerifyAppEventParam(AppEventParam& param, std::unordered_set<std::string>& paramNames, int& verifyRes)
182 {
183     std::string name = param.name;
184     if (paramNames.find(name) != paramNames.end()) {
185         HiLog::Warn(LABEL, "param=%{public}s is discarded because param is duplicate.", name.c_str());
186         verifyRes = ERROR_DUPLICATE_PARAM;
187         return false;
188     }
189 
190     if (!CheckParamName(name)) {
191         HiLog::Warn(LABEL, "param=%{public}s is discarded because the paramName is invalid.", name.c_str());
192         verifyRes = ERROR_INVALID_PARAM_NAME;
193         return false;
194     }
195 
196     const std::unordered_set<std::string> tempTrueNames = {"crash", "anr"};
197     size_t maxLen = tempTrueNames.find(name) == tempTrueNames.end() ? MAX_LENGTH_OF_STR_PARAM :
198         MAX_LENGTH_OF_SPECIAL_STR_PARAM;
199     if (param.type == AppEventParamType::STRING && !CheckStrParamLength(param.value.valueUnion.str_, maxLen)) {
200         HiLog::Warn(LABEL, "param=%{public}s is discarded because the string length exceeds %{public}zu.",
201             name.c_str(), maxLen);
202         verifyRes = ERROR_INVALID_PARAM_VALUE_LENGTH;
203         return false;
204     }
205 
206     if (param.type == AppEventParamType::STRVECTOR && !CheckStringLengthOfList(param.value.valueUnion.strs_)) {
207         HiLog::Warn(LABEL, "param=%{public}s is discarded because the string length of list exceeds 8192.",
208             name.c_str());
209         verifyRes = ERROR_INVALID_PARAM_VALUE_LENGTH;
210         return false;
211     }
212 
213     if (param.type > AppEventParamType::STRING && !CheckListValueSize(param.type, param.value.valueUnion)) {
214         HiLog::Warn(LABEL, "list param=%{public}s is truncated because the list size exceeds 100.", name.c_str());
215         verifyRes = ERROR_INVALID_LIST_PARAM_SIZE;
216         return true;
217     }
218     return true;
219 }
220 
221 using VerifyReportConfigFunc = int (*)(ReportConfig& config);
VerifyNameOfReportConfig(ReportConfig & config)222 int VerifyNameOfReportConfig(ReportConfig& config)
223 {
224     if (!IsValidProcessorName(config.name)) {
225         HiLog::Error(LABEL, "invalid name=%{public}s", config.name.c_str());
226         return -1;
227     }
228     return 0;
229 }
230 
VerifyRouteInfoOfReportConfig(ReportConfig & config)231 int VerifyRouteInfoOfReportConfig(ReportConfig& config)
232 {
233     if (!IsValidRouteInfo(config.routeInfo)) {
234         HiLog::Warn(LABEL, "invalid routeInfo=%{public}s", config.routeInfo.c_str());
235         config.routeInfo = "";
236     }
237     return 0;
238 }
239 
VerifyAppIdOfReportConfig(ReportConfig & config)240 int VerifyAppIdOfReportConfig(ReportConfig& config)
241 {
242     if (!IsValidAppId(config.appId)) {
243         HiLog::Warn(LABEL, "invalid appId=%{public}s", config.appId.c_str());
244         config.appId = "";
245     }
246     return 0;
247 }
248 
VerifyTriggerCondOfReportConfig(ReportConfig & config)249 int VerifyTriggerCondOfReportConfig(ReportConfig& config)
250 {
251     if (!IsValidBatchReport(config.triggerCond.row)) {
252         HiLog::Warn(LABEL, "invalid triggerCond.row=%{public}d", config.triggerCond.row);
253         config.triggerCond.row = 0;
254     }
255     if (!IsValidPeriodReport(config.triggerCond.timeout)) {
256         HiLog::Warn(LABEL, "invalid triggerCond.timeout=%{public}d", config.triggerCond.row);
257         config.triggerCond.timeout = 0;
258     }
259     // processor does not support the size
260     config.triggerCond.size = 0;
261     return 0;
262 }
263 
VerifyUserIdNamesOfReportConfig(ReportConfig & config)264 int VerifyUserIdNamesOfReportConfig(ReportConfig& config)
265 {
266     for (const auto& name : config.userIdNames) {
267         if (!IsValidUserIdName(name)) {
268             HiLog::Warn(LABEL, "invalid user id name=%{public}s", name.c_str());
269             config.userIdNames.clear();
270             break;
271         }
272     }
273     return 0;
274 }
275 
VerifyUserPropertyNamesOfReportConfig(ReportConfig & config)276 int VerifyUserPropertyNamesOfReportConfig(ReportConfig& config)
277 {
278     for (const auto& name : config.userPropertyNames) {
279         if (!IsValidUserIdName(name)) {
280             HiLog::Warn(LABEL, "invalid user property name=%{public}s", name.c_str());
281             config.userPropertyNames.clear();
282             break;
283         }
284     }
285     return 0;
286 }
287 
VerifyEventConfigsOfReportConfig(ReportConfig & reportConfig)288 int VerifyEventConfigsOfReportConfig(ReportConfig& reportConfig)
289 {
290     for (const auto& eventConfig : reportConfig.eventConfigs) {
291         if (!IsValidEventConfig(eventConfig)) {
292             HiLog::Warn(LABEL, "invalid event configs, domain=%{public}s, name=%{public}s",
293                 eventConfig.domain.c_str(), eventConfig.name.c_str());
294             reportConfig.eventConfigs.clear();
295             break;
296         }
297     }
298     return 0;
299 }
300 }
301 
IsValidDomain(const std::string & eventDomain)302 bool IsValidDomain(const std::string& eventDomain)
303 {
304     if (eventDomain.empty() || eventDomain.length() > MAX_LEN_OF_DOMAIN) {
305         return false;
306     }
307     if (eventDomain != "OS" && !std::regex_match(eventDomain, std::regex("^[a-z]([a-z0-9_]*[a-z0-9])*$"))) {
308         return false;
309     }
310     return true;
311 }
312 
IsValidEventName(const std::string & eventName)313 bool IsValidEventName(const std::string& eventName)
314 {
315     const std::string eventPrefix = "hiappevent.";
316     return eventName.find(eventPrefix) == 0 ?
317         IsValidName(eventName.substr(eventPrefix.length()), MAX_LENGTH_OF_EVENT_NAME - eventPrefix.length()) :
318         IsValidName(eventName, MAX_LENGTH_OF_EVENT_NAME);
319 }
320 
IsValidWatcherName(const std::string & watcherName)321 bool IsValidWatcherName(const std::string& watcherName)
322 {
323     if (watcherName.empty() || watcherName.length() > MAX_LEN_OF_WATCHER) {
324         return false;
325     }
326     return std::regex_match(watcherName, std::regex("^[a-z]([a-z0-9_]*[a-z0-9])*$"));
327 }
328 
IsValidEventType(int eventType)329 bool IsValidEventType(int eventType)
330 {
331     return eventType >= 1 && eventType <= 4; // 1-4: value range of event type
332 }
333 
VerifyAppEvent(std::shared_ptr<AppEventPack> event)334 int VerifyAppEvent(std::shared_ptr<AppEventPack> event)
335 {
336     if (HiAppEventConfig::GetInstance().GetDisable()) {
337         HiLog::Error(LABEL, "the HiAppEvent function is disabled.");
338         return ERROR_HIAPPEVENT_DISABLE;
339     }
340     if (!IsValidDomain(event->GetDomain())) {
341         HiLog::Error(LABEL, "eventDomain=%{public}s is invalid.", event->GetDomain().c_str());
342         return ERROR_INVALID_EVENT_DOMAIN;
343     }
344     if (!IsValidEventName(event->GetName())) {
345         HiLog::Error(LABEL, "eventName=%{public}s is invalid.", event->GetName().c_str());
346         return ERROR_INVALID_EVENT_NAME;
347     }
348 
349     int verifyRes = HIAPPEVENT_VERIFY_SUCCESSFUL;
350     std::list<AppEventParam>& baseParams = event->baseParams_;
351     std::unordered_set<std::string> paramNames;
352     for (auto it = baseParams.begin(); it != baseParams.end();) {
353         if (!VerifyAppEventParam(*it, paramNames, verifyRes)) {
354             baseParams.erase(it++);
355             continue;
356         }
357         paramNames.emplace(it->name);
358         it++;
359     }
360 
361     if (!CheckParamsNum(baseParams)) {
362         HiLog::Warn(LABEL, "params that exceed 32 are discarded because the number of params cannot exceed 32.");
363         verifyRes = ERROR_INVALID_PARAM_NUM;
364     }
365 
366     return verifyRes;
367 }
368 
IsValidPropName(const std::string & name,size_t maxSize)369 bool IsValidPropName(const std::string& name, size_t maxSize)
370 {
371     if (name.empty() || name.length() > maxSize) {
372         return false;
373     }
374     // start char is [a-zA-Z_$]
375     if (!isalpha(name[0]) && name[0] != '_' && name[0] != '$') {
376         return false;
377     }
378     // other char is [a-zA-Z0-9_$]
379     for (size_t i = 1; i < name.length(); ++i) {
380         if (!isalnum(name[i]) && name[i] != '_' && name[i] != '$') {
381             return false;
382         }
383     }
384     return true;
385 }
386 
IsValidPropValue(const std::string & val,size_t maxSize)387 bool IsValidPropValue(const std::string& val, size_t maxSize)
388 {
389     return !val.empty() && val.length() <= maxSize;
390 }
391 
IsValidProcessorName(const std::string & name)392 bool IsValidProcessorName(const std::string& name)
393 {
394     return IsValidPropName(name, MAX_LENGTH_OF_PROCESSOR_NAME);
395 }
396 
IsValidRouteInfo(const std::string & name)397 bool IsValidRouteInfo(const std::string& name)
398 {
399     return name.length() <= MAX_LENGTH_OF_STR_PARAM;
400 }
401 
IsValidAppId(const std::string & name)402 bool IsValidAppId(const std::string& name)
403 {
404     return name.length() <= MAX_LENGTH_OF_STR_PARAM;
405 }
406 
IsValidPeriodReport(int timeout)407 bool IsValidPeriodReport(int timeout)
408 {
409     return timeout >= 0;
410 }
411 
IsValidBatchReport(int count)412 bool IsValidBatchReport(int count)
413 {
414     return count >= 0 && count <= MAX_LEN_OF_BATCH_REPORT;
415 }
416 
IsValidUserIdName(const std::string & name)417 bool IsValidUserIdName(const std::string& name)
418 {
419     return IsValidPropName(name, MAX_LENGTH_OF_USER_INFO_NAME);
420 }
421 
IsValidUserIdValue(const std::string & value)422 bool IsValidUserIdValue(const std::string& value)
423 {
424     return IsValidPropValue(value, MAX_LENGTH_OF_USER_ID_VALUE);
425 }
426 
IsValidUserPropName(const std::string & name)427 bool IsValidUserPropName(const std::string& name)
428 {
429     return IsValidPropName(name, MAX_LENGTH_OF_USER_INFO_NAME);
430 }
431 
IsValidUserPropValue(const std::string & value)432 bool IsValidUserPropValue(const std::string& value)
433 {
434     return IsValidPropValue(value, MAX_LENGTH_OF_USER_PROPERTY_VALUE);
435 }
436 
IsValidEventConfig(const EventConfig & eventCfg)437 bool IsValidEventConfig(const EventConfig& eventCfg)
438 {
439     if (eventCfg.domain.empty() && eventCfg.name.empty()) {
440         return false;
441     }
442     if (!eventCfg.domain.empty() && !IsValidDomain(eventCfg.domain)) {
443         return false;
444     }
445     if (!eventCfg.name.empty() && !IsValidEventName(eventCfg.name)) {
446         return false;
447     }
448     return true;
449 }
450 
VerifyReportConfig(ReportConfig & config)451 int VerifyReportConfig(ReportConfig& config)
452 {
453     const VerifyReportConfigFunc verifyFuncs[] = {
454         VerifyNameOfReportConfig,
455         VerifyRouteInfoOfReportConfig,
456         VerifyAppIdOfReportConfig,
457         VerifyTriggerCondOfReportConfig,
458         VerifyUserIdNamesOfReportConfig,
459         VerifyUserPropertyNamesOfReportConfig,
460         VerifyEventConfigsOfReportConfig,
461     };
462     for (const auto verifyFunc : verifyFuncs) {
463         if (verifyFunc(config) != 0) {
464             return -1;
465         }
466     }
467     return 0;
468 }
469 } // namespace HiviewDFX
470 } // namespace OHOS
471