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
22 #include "hiappevent_base.h"
23 #include "hiappevent_config.h"
24 #include "hilog/log.h"
25
26 using namespace OHOS::HiviewDFX::ErrorCode;
27
28 namespace OHOS {
29 namespace HiviewDFX {
30 namespace {
31 static constexpr HiLogLabel LABEL = { LOG_CORE, HIAPPEVENT_DOMAIN, "HiAppEvent_verify" };
32
33 constexpr size_t MAX_LEN_OF_WATCHER = 32;
34 constexpr size_t MAX_LEN_OF_DOMAIN = 16;
35 static constexpr int MAX_LENGTH_OF_EVENT_NAME = 48;
36 static constexpr int MAX_LENGTH_OF_PARAM_NAME = 16;
37 static constexpr unsigned int MAX_NUM_OF_PARAMS = 32;
38 static constexpr int MAX_LENGTH_OF_STR_PARAM = 8 * 1024;
39 static constexpr int MAX_SIZE_OF_LIST_PARAM = 100;
40
IsValidName(const std::string & name,size_t maxSize)41 bool IsValidName(const std::string& name, size_t maxSize)
42 {
43 if (name.empty() || name.length() > maxSize) {
44 return false;
45 }
46 // start char is [$a-zA-Z]
47 if (!isalpha(name[0]) && name[0] != '$') {
48 return false;
49 }
50 // end char is [a-zA-Z0-9]
51 if (name.length() > 1 && (!isalnum(name.back()))) {
52 return false;
53 }
54 // middle char is [a-zA-Z0-9_]
55 for (size_t i = 1; i < name.length() - 1; ++i) {
56 if (!isalnum(name[i]) && name[i] != '_') {
57 return false;
58 }
59 }
60 return true;
61 }
62
CheckEventName(const std::string & eventName)63 bool CheckEventName(const std::string& eventName)
64 {
65 const std::string eventPrefix = "hiappevent.";
66 return eventName.find(eventPrefix) == 0 ?
67 IsValidName(eventName.substr(eventPrefix.length()), MAX_LENGTH_OF_EVENT_NAME - eventPrefix.length()) :
68 IsValidName(eventName, MAX_LENGTH_OF_EVENT_NAME);
69 }
70
CheckParamName(const std::string & paramName)71 bool CheckParamName(const std::string& paramName)
72 {
73 return IsValidName(paramName, MAX_LENGTH_OF_PARAM_NAME);
74 }
75
EscapeStringValue(std::string & value)76 void EscapeStringValue(std::string &value)
77 {
78 std::string escapeValue;
79 for (auto it = value.begin(); it != value.end(); it++) {
80 switch (*it) {
81 case '\\':
82 escapeValue.append("\\\\");
83 break;
84 case '\"':
85 escapeValue.append("\\\"");
86 break;
87 case '\b':
88 escapeValue.append("\\b");
89 break;
90 case '\f':
91 escapeValue.append("\\f");
92 break;
93 case '\n':
94 escapeValue.append("\\n");
95 break;
96 case '\r':
97 escapeValue.append("\\r");
98 break;
99 case '\t':
100 escapeValue.append("\\t");
101 break;
102 default:
103 escapeValue.push_back(*it);
104 break;
105 }
106 }
107 value = escapeValue;
108 }
109
CheckStrParamLength(std::string & strParamValue)110 bool CheckStrParamLength(std::string& strParamValue)
111 {
112 if (strParamValue.empty()) {
113 HiLog::Warn(LABEL, "str param value is empty.");
114 return true;
115 }
116
117 if (strParamValue.length() > MAX_LENGTH_OF_STR_PARAM) {
118 return false;
119 }
120
121 EscapeStringValue(strParamValue);
122 return true;
123 }
124
CheckListValueSize(AppEventParamType type,AppEventParamValue::ValueUnion & vu)125 bool CheckListValueSize(AppEventParamType type, AppEventParamValue::ValueUnion& vu)
126 {
127 if (type == AppEventParamType::BVECTOR && vu.bs_.size() > MAX_SIZE_OF_LIST_PARAM) {
128 vu.bs_.resize(MAX_SIZE_OF_LIST_PARAM);
129 } else if (type == AppEventParamType::CVECTOR && vu.cs_.size() > MAX_SIZE_OF_LIST_PARAM) {
130 vu.cs_.resize(MAX_SIZE_OF_LIST_PARAM);
131 } else if (type == AppEventParamType::SHVECTOR && vu.shs_.size() > MAX_SIZE_OF_LIST_PARAM) {
132 vu.shs_.resize(MAX_SIZE_OF_LIST_PARAM);
133 } else if (type == AppEventParamType::IVECTOR && vu.is_.size() > MAX_SIZE_OF_LIST_PARAM) {
134 vu.is_.resize(MAX_SIZE_OF_LIST_PARAM);
135 } else if (type == AppEventParamType::LLVECTOR && vu.lls_.size() > MAX_SIZE_OF_LIST_PARAM) {
136 vu.lls_.resize(MAX_SIZE_OF_LIST_PARAM);
137 } else if (type == AppEventParamType::FVECTOR && vu.fs_.size() > MAX_SIZE_OF_LIST_PARAM) {
138 vu.fs_.resize(MAX_SIZE_OF_LIST_PARAM);
139 } else if (type == AppEventParamType::DVECTOR && vu.ds_.size() > MAX_SIZE_OF_LIST_PARAM) {
140 vu.ds_.resize(MAX_SIZE_OF_LIST_PARAM);
141 } else if (type == AppEventParamType::STRVECTOR && vu.strs_.size() > MAX_SIZE_OF_LIST_PARAM) {
142 vu.strs_.resize(MAX_SIZE_OF_LIST_PARAM);
143 } else {
144 return true;
145 }
146
147 return false;
148 }
149
CheckStringLengthOfList(std::vector<std::string> & strs)150 bool CheckStringLengthOfList(std::vector<std::string>& strs)
151 {
152 if (strs.empty()) {
153 return true;
154 }
155
156 for (auto it = strs.begin(); it != strs.end(); it++) {
157 if (!CheckStrParamLength(*it)) {
158 return false;
159 }
160 }
161
162 return true;
163 }
164
CheckParamsNum(std::list<AppEventParam> & baseParams)165 bool CheckParamsNum(std::list<AppEventParam>& baseParams)
166 {
167 if (baseParams.size() == 0) {
168 return true;
169 }
170
171 auto listSize = baseParams.size();
172 if (listSize > MAX_NUM_OF_PARAMS) {
173 auto delStartPtr = baseParams.begin();
174 std::advance(delStartPtr, MAX_NUM_OF_PARAMS);
175 baseParams.erase(delStartPtr, baseParams.end());
176 return false;
177 }
178
179 return true;
180 }
181 }
182
IsValidDomain(const std::string & eventDomain)183 bool IsValidDomain(const std::string& eventDomain)
184 {
185 if (eventDomain.empty() || eventDomain.length() > MAX_LEN_OF_DOMAIN) {
186 return false;
187 }
188 if (!std::regex_match(eventDomain, std::regex("^[a-z][a-z0-9_]*[a-z0-9]$"))) {
189 return false;
190 }
191 return true;
192 }
193
IsValidWatcherName(const std::string & watcherName)194 bool IsValidWatcherName(const std::string& watcherName)
195 {
196 if (watcherName.empty() || watcherName.length() > MAX_LEN_OF_WATCHER) {
197 return false;
198 }
199 return std::regex_match(watcherName, std::regex("^[a-z][a-z0-9_]*[a-z0-9]$"));
200 }
201
IsValidEventType(int eventType)202 bool IsValidEventType(int eventType)
203 {
204 return eventType >= 1 && eventType <= 4; // 1-4: value range of event type
205 }
206
VerifyAppEvent(std::shared_ptr<AppEventPack> & appEventPack)207 int VerifyAppEvent(std::shared_ptr<AppEventPack>& appEventPack)
208 {
209 if (HiAppEventConfig::GetInstance().GetDisable()) {
210 HiLog::Error(LABEL, "the HiAppEvent function is disabled.");
211 return ERROR_HIAPPEVENT_DISABLE;
212 }
213 if (!IsValidDomain(appEventPack->GetEventDomain())) {
214 HiLog::Error(LABEL, "eventDomain=%{public}s is invalid.", appEventPack->GetEventDomain().c_str());
215 return ERROR_INVALID_EVENT_DOMAIN;
216 }
217 if (!CheckEventName(appEventPack->GetEventName())) {
218 HiLog::Error(LABEL, "eventName=%{public}s is invalid.", appEventPack->GetEventName().c_str());
219 return ERROR_INVALID_EVENT_NAME;
220 }
221
222 int verifyRes = HIAPPEVENT_VERIFY_SUCCESSFUL;
223 std::list<AppEventParam>& baseParams = appEventPack->baseParams_;
224 if (!CheckParamsNum(baseParams)) {
225 HiLog::Warn(LABEL, "params that exceed 32 are discarded because the number of params cannot exceed 32.");
226 verifyRes = ERROR_INVALID_PARAM_NUM;
227 }
228
229 for (auto it = baseParams.begin(); it != baseParams.end();) {
230 if (!CheckParamName(it->name)) {
231 HiLog::Warn(LABEL, "param=%{public}s is discarded because the paramName is invalid.", it->name.c_str());
232 verifyRes = ERROR_INVALID_PARAM_NAME;
233 baseParams.erase(it++);
234 continue;
235 }
236
237 if (it->type == AppEventParamType::STRING && !CheckStrParamLength(it->value.valueUnion.str_)) {
238 HiLog::Warn(LABEL, "param=%{public}s is discarded because the string length exceeds 8192.",
239 it->name.c_str());
240 verifyRes = ERROR_INVALID_PARAM_VALUE_LENGTH;
241 baseParams.erase(it++);
242 continue;
243 }
244
245 if (it->type > AppEventParamType::STRING && !CheckListValueSize(it->type, it->value.valueUnion)) {
246 HiLog::Warn(LABEL, "list param=%{public}s is truncated because the list size exceeds 100.",
247 it->name.c_str());
248 verifyRes = ERROR_INVALID_LIST_PARAM_SIZE;
249 continue;
250 }
251
252 if (it->type == AppEventParamType::STRVECTOR && !CheckStringLengthOfList(it->value.valueUnion.strs_)) {
253 HiLog::Warn(LABEL, "param=%{public}s is discarded because the string length of list exceeds 8192.",
254 it->name.c_str());
255 verifyRes = ERROR_INVALID_PARAM_VALUE_LENGTH;
256 baseParams.erase(it++);
257 continue;
258 }
259 it++;
260 }
261
262 return verifyRes;
263 }
264 } // namespace HiviewDFX
265 } // namespace OHOS
266