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