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 "ipc_cparcel.h"
17 #include "ipc_error_code.h"
18 #include "message_parcel.h"
19 #include "log_tags.h"
20 #include "ipc_debug.h"
21 #include "ipc_internal_utils.h"
22 #include "ipc_inner_object.h"
23
24 #include <securec.h>
25
26 static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = { LOG_CORE, OHOS::LOG_ID_IPC_CAPI, "OHIPCParcel" };
27
OH_IPCParcel_Create(void)28 OHIPCParcel* OH_IPCParcel_Create(void)
29 {
30 OHOS::MessageParcel *msgParcel = new (std::nothrow) OHOS::MessageParcel();
31 if (msgParcel == nullptr) {
32 ZLOGE(LOG_LABEL, "message parcel is null!");
33 return nullptr;
34 }
35 OHIPCParcel *parcel = new (std::nothrow) OHIPCParcel();
36 if (parcel == nullptr) {
37 ZLOGE(LOG_LABEL, "ipc parcel is null!");
38 delete msgParcel;
39 return nullptr;
40 }
41 parcel->msgParcel = msgParcel;
42 return parcel;
43 }
44
OH_IPCParcel_Destroy(OHIPCParcel * parcel)45 void OH_IPCParcel_Destroy(OHIPCParcel *parcel)
46 {
47 if (parcel != nullptr) {
48 if (parcel->msgParcel != nullptr) {
49 delete parcel->msgParcel;
50 parcel->msgParcel = nullptr;
51 }
52 delete parcel;
53 }
54 }
55
56 template <typename T, typename U>
SetParcelProperty(OHIPCParcel * parcel,T value,bool (OHOS::MessageParcel::* SetProperty)(U value))57 static int SetParcelProperty(OHIPCParcel *parcel, T value, bool (OHOS::MessageParcel::*SetProperty)(U value))
58 {
59 if (!IsIPCParcelValid(parcel, __func__)) {
60 return OH_IPC_CHECK_PARAM_ERROR;
61 }
62 return (parcel->msgParcel->*SetProperty)(static_cast<U>(value)) ? OH_IPC_SUCCESS
63 : OH_IPC_INNER_ERROR;
64 }
65
66 template <typename T, typename U>
GetParcelPropertyConst(const OHIPCParcel * parcel,U (OHOS::MessageParcel::* GetProperty)()const)67 static T GetParcelPropertyConst(const OHIPCParcel *parcel, U (OHOS::MessageParcel::*GetProperty)() const)
68 {
69 if (!IsIPCParcelValid(parcel, __func__)) {
70 return -1;
71 }
72 return static_cast<T>((parcel->msgParcel->*GetProperty)());
73 }
74
75 template <typename T, typename U>
GetParcelProperty(const OHIPCParcel * parcel,U (OHOS::MessageParcel::* GetProperty)())76 static T GetParcelProperty(const OHIPCParcel *parcel, U (OHOS::MessageParcel::*GetProperty)())
77 {
78 if (!IsIPCParcelValid(parcel, __func__)) {
79 return -1;
80 }
81 return static_cast<T>((parcel->msgParcel->*GetProperty)());
82 }
83
OH_IPCParcel_GetDataSize(const OHIPCParcel * parcel)84 int OH_IPCParcel_GetDataSize(const OHIPCParcel *parcel)
85 {
86 return GetParcelPropertyConst<int, size_t>(parcel, &OHOS::MessageParcel::GetDataSize);
87 }
88
OH_IPCParcel_GetWritableBytes(const OHIPCParcel * parcel)89 int OH_IPCParcel_GetWritableBytes(const OHIPCParcel *parcel)
90 {
91 return GetParcelPropertyConst<int, size_t>(parcel, &OHOS::MessageParcel::GetWritableBytes);
92 }
93
OH_IPCParcel_GetReadableBytes(const OHIPCParcel * parcel)94 int OH_IPCParcel_GetReadableBytes(const OHIPCParcel *parcel)
95 {
96 return GetParcelPropertyConst<int, size_t>(parcel, &OHOS::MessageParcel::GetReadableBytes);
97 }
98
OH_IPCParcel_GetReadPosition(const OHIPCParcel * parcel)99 int OH_IPCParcel_GetReadPosition(const OHIPCParcel *parcel)
100 {
101 return GetParcelProperty<int, size_t>(parcel, &OHOS::MessageParcel::GetReadPosition);
102 }
103
OH_IPCParcel_GetWritePosition(const OHIPCParcel * parcel)104 int OH_IPCParcel_GetWritePosition(const OHIPCParcel *parcel)
105 {
106 return GetParcelProperty<int, size_t>(parcel, &OHOS::MessageParcel::GetWritePosition);
107 }
108
OH_IPCParcel_RewindReadPosition(OHIPCParcel * parcel,uint32_t newReadPos)109 int OH_IPCParcel_RewindReadPosition(OHIPCParcel *parcel, uint32_t newReadPos)
110 {
111 return SetParcelProperty<uint32_t, size_t>(parcel, newReadPos, &OHOS::MessageParcel::RewindRead);
112 }
113
OH_IPCParcel_RewindWritePosition(OHIPCParcel * parcel,uint32_t newWritePos)114 int OH_IPCParcel_RewindWritePosition(OHIPCParcel *parcel, uint32_t newWritePos)
115 {
116 return SetParcelProperty<uint32_t, size_t>(parcel, newWritePos, &OHOS::MessageParcel::RewindWrite);
117 }
118
119 template <typename T>
WriteValue(OHIPCParcel * parcel,T value,bool (OHOS::MessageParcel::* Write)(T value))120 static int WriteValue(OHIPCParcel *parcel, T value, bool (OHOS::MessageParcel::*Write)(T value))
121 {
122 if (!IsIPCParcelValid(parcel, __func__)) {
123 return OH_IPC_CHECK_PARAM_ERROR;
124 }
125 return (parcel->msgParcel->*Write)(value) ? OH_IPC_SUCCESS : OH_IPC_PARCEL_WRITE_ERROR;
126 }
127
128 template <typename T>
ReadValue(const OHIPCParcel * parcel,T * value,bool (OHOS::MessageParcel::* Read)(T & value))129 static int ReadValue(const OHIPCParcel *parcel, T* value, bool (OHOS::MessageParcel::*Read)(T& value))
130 {
131 if (!IsIPCParcelValid(parcel, __func__) || value == nullptr) {
132 return OH_IPC_CHECK_PARAM_ERROR;
133 }
134
135 return (parcel->msgParcel->*Read)(*value) ? OH_IPC_SUCCESS : OH_IPC_PARCEL_READ_ERROR;
136 }
137
OH_IPCParcel_WriteInt8(OHIPCParcel * parcel,int8_t value)138 int OH_IPCParcel_WriteInt8(OHIPCParcel *parcel, int8_t value)
139 {
140 return WriteValue<int8_t>(parcel, value, &OHOS::MessageParcel::WriteInt8);
141 }
142
OH_IPCParcel_ReadInt8(const OHIPCParcel * parcel,int8_t * value)143 int OH_IPCParcel_ReadInt8(const OHIPCParcel *parcel, int8_t *value)
144 {
145 return ReadValue<int8_t>(parcel, value, &OHOS::MessageParcel::ReadInt8);
146 }
147
OH_IPCParcel_WriteInt16(OHIPCParcel * parcel,int16_t value)148 int OH_IPCParcel_WriteInt16(OHIPCParcel *parcel, int16_t value)
149 {
150 return WriteValue<int16_t>(parcel, value, &OHOS::MessageParcel::WriteInt16);
151 }
152
OH_IPCParcel_ReadInt16(const OHIPCParcel * parcel,int16_t * value)153 int OH_IPCParcel_ReadInt16(const OHIPCParcel *parcel, int16_t *value)
154 {
155 return ReadValue<int16_t>(parcel, value, &OHOS::MessageParcel::ReadInt16);
156 }
157
OH_IPCParcel_WriteInt32(OHIPCParcel * parcel,int32_t value)158 int OH_IPCParcel_WriteInt32(OHIPCParcel *parcel, int32_t value)
159 {
160 return WriteValue<int32_t>(parcel, value, &OHOS::MessageParcel::WriteInt32);
161 }
162
OH_IPCParcel_ReadInt32(const OHIPCParcel * parcel,int32_t * value)163 int OH_IPCParcel_ReadInt32(const OHIPCParcel *parcel, int32_t *value)
164 {
165 return ReadValue<int32_t>(parcel, value, &OHOS::MessageParcel::ReadInt32);
166 }
167
OH_IPCParcel_WriteInt64(OHIPCParcel * parcel,int64_t value)168 int OH_IPCParcel_WriteInt64(OHIPCParcel *parcel, int64_t value)
169 {
170 return WriteValue<int64_t>(parcel, value, &OHOS::MessageParcel::WriteInt64);
171 }
172
OH_IPCParcel_ReadInt64(const OHIPCParcel * parcel,int64_t * value)173 int OH_IPCParcel_ReadInt64(const OHIPCParcel *parcel, int64_t *value)
174 {
175 return ReadValue<int64_t>(parcel, value, &OHOS::MessageParcel::ReadInt64);
176 }
177
OH_IPCParcel_WriteFloat(OHIPCParcel * parcel,float value)178 int OH_IPCParcel_WriteFloat(OHIPCParcel *parcel, float value)
179 {
180 return WriteValue<float>(parcel, value, &OHOS::MessageParcel::WriteFloat);
181 }
182
OH_IPCParcel_ReadFloat(const OHIPCParcel * parcel,float * value)183 int OH_IPCParcel_ReadFloat(const OHIPCParcel *parcel, float *value)
184 {
185 return ReadValue<float>(parcel, value, &OHOS::MessageParcel::ReadFloat);
186 }
187
OH_IPCParcel_WriteDouble(OHIPCParcel * parcel,double value)188 int OH_IPCParcel_WriteDouble(OHIPCParcel *parcel, double value)
189 {
190 return WriteValue<double>(parcel, value, &OHOS::MessageParcel::WriteDouble);
191 }
192
OH_IPCParcel_ReadDouble(const OHIPCParcel * parcel,double * value)193 int OH_IPCParcel_ReadDouble(const OHIPCParcel *parcel, double *value)
194 {
195 return ReadValue<double>(parcel, value, &OHOS::MessageParcel::ReadDouble);
196 }
197
OH_IPCParcel_WriteString(OHIPCParcel * parcel,const char * str)198 int OH_IPCParcel_WriteString(OHIPCParcel *parcel, const char *str)
199 {
200 if (!IsIPCParcelValid(parcel, __func__) || str == nullptr) {
201 return OH_IPC_CHECK_PARAM_ERROR;
202 }
203
204 return parcel->msgParcel->WriteCString(str) ? OH_IPC_SUCCESS : OH_IPC_PARCEL_WRITE_ERROR;
205 }
206
OH_IPCParcel_ReadString(const OHIPCParcel * parcel)207 const char* OH_IPCParcel_ReadString(const OHIPCParcel *parcel)
208 {
209 if (!IsIPCParcelValid(parcel, __func__)) {
210 return nullptr;
211 }
212
213 return parcel->msgParcel->ReadCString();
214 }
215
OH_IPCParcel_WriteBuffer(OHIPCParcel * parcel,const uint8_t * buffer,int32_t len)216 int OH_IPCParcel_WriteBuffer(OHIPCParcel *parcel, const uint8_t *buffer, int32_t len)
217 {
218 if (!IsIPCParcelValid(parcel, __func__) || buffer == nullptr || len <= 0) {
219 return OH_IPC_CHECK_PARAM_ERROR;
220 }
221
222 size_t writePosition = parcel->msgParcel->GetWritePosition();
223 if (!parcel->msgParcel->WriteBuffer(buffer, len)) {
224 ZLOGE(LOG_LABEL, "write buffer failed! buffer len:%{public}d", len);
225 parcel->msgParcel->RewindWrite(writePosition);
226 return OH_IPC_PARCEL_WRITE_ERROR;
227 }
228 return OH_IPC_SUCCESS;
229 }
230
OH_IPCParcel_ReadBuffer(const OHIPCParcel * parcel,int32_t len)231 const uint8_t* OH_IPCParcel_ReadBuffer(const OHIPCParcel *parcel, int32_t len)
232 {
233 if (!IsIPCParcelValid(parcel, __func__)) {
234 return nullptr;
235 }
236 int readableBytes = static_cast<int>(parcel->msgParcel->GetReadableBytes());
237 if (len <= 0 || len > readableBytes) {
238 ZLOGE(LOG_LABEL, "read buf len:%{public}d invalid! ReadableBytes:%{public}d", len, readableBytes);
239 return nullptr;
240 }
241
242 return parcel->msgParcel->ReadBuffer(len);
243 }
244
245 template <typename T>
WriteIPCRemoteObject(OHIPCParcel * parcel,const T * object)246 static int WriteIPCRemoteObject(OHIPCParcel *parcel, const T *object)
247 {
248 if (!IsIPCParcelValid(parcel, __func__) || object == nullptr) {
249 return OH_IPC_CHECK_PARAM_ERROR;
250 }
251 if (!parcel->msgParcel->WriteRemoteObject(object->remote)) {
252 ZLOGE(LOG_LABEL, "write remote object failed!");
253 return OH_IPC_PARCEL_WRITE_ERROR;
254 }
255 return OH_IPC_SUCCESS;
256 }
257
258 template <typename T>
ReadIPCRemoteObject(const OHIPCParcel * parcel)259 static T* ReadIPCRemoteObject(const OHIPCParcel *parcel)
260 {
261 if (!IsIPCParcelValid(parcel, __func__)) {
262 return nullptr;
263 }
264 OHOS::sptr<OHOS::IRemoteObject> object = parcel->msgParcel->ReadRemoteObject();
265 if (object == nullptr) {
266 ZLOGE(LOG_LABEL, "read remote object failed!");
267 return nullptr;
268 }
269 T *remoteObject = new (std::nothrow) T();
270 if (remoteObject == nullptr) {
271 ZLOGE(LOG_LABEL, "new remote object failed");
272 return nullptr;
273 }
274 remoteObject->remote = object;
275 return remoteObject;
276 }
277
OH_IPCParcel_WriteRemoteStub(OHIPCParcel * parcel,const OHIPCRemoteStub * stub)278 int OH_IPCParcel_WriteRemoteStub(OHIPCParcel *parcel, const OHIPCRemoteStub *stub)
279 {
280 return WriteIPCRemoteObject(parcel, stub);
281 }
282
OH_IPCParcel_ReadRemoteStub(const OHIPCParcel * parcel)283 OHIPCRemoteStub* OH_IPCParcel_ReadRemoteStub(const OHIPCParcel *parcel)
284 {
285 return ReadIPCRemoteObject<OHIPCRemoteStub>(parcel);
286 }
287
OH_IPCParcel_WriteRemoteProxy(OHIPCParcel * parcel,const OHIPCRemoteProxy * proxy)288 int OH_IPCParcel_WriteRemoteProxy(OHIPCParcel *parcel, const OHIPCRemoteProxy *proxy)
289 {
290 return WriteIPCRemoteObject(parcel, proxy);
291 }
292
OH_IPCParcel_ReadRemoteProxy(const OHIPCParcel * parcel)293 OHIPCRemoteProxy* OH_IPCParcel_ReadRemoteProxy(const OHIPCParcel *parcel)
294 {
295 return ReadIPCRemoteObject<OHIPCRemoteProxy>(parcel);
296 }
297
OH_IPCParcel_WriteFileDescriptor(OHIPCParcel * parcel,int32_t fd)298 int OH_IPCParcel_WriteFileDescriptor(OHIPCParcel *parcel, int32_t fd)
299 {
300 return WriteValue<int32_t>(parcel, fd, &OHOS::MessageParcel::WriteFileDescriptor);
301 }
302
OH_IPCParcel_ReadFileDescriptor(const OHIPCParcel * parcel,int32_t * fd)303 int OH_IPCParcel_ReadFileDescriptor(const OHIPCParcel *parcel, int32_t *fd)
304 {
305 if (!IsIPCParcelValid(parcel, __func__) || fd == nullptr) {
306 return OH_IPC_CHECK_PARAM_ERROR;
307 }
308
309 int tmpFd = parcel->msgParcel->ReadFileDescriptor();
310 if (tmpFd == -1) {
311 ZLOGE(LOG_LABEL, "read file descriptor failed!");
312 return OH_IPC_PARCEL_READ_ERROR;
313 }
314 *fd = tmpFd;
315 return OH_IPC_SUCCESS;
316 }
317
OH_IPCParcel_Append(OHIPCParcel * parcel,const OHIPCParcel * data)318 int OH_IPCParcel_Append(OHIPCParcel *parcel, const OHIPCParcel *data)
319 {
320 if (!IsIPCParcelValid(parcel, __func__)
321 || !IsIPCParcelValid(data, __func__)) {
322 return OH_IPC_CHECK_PARAM_ERROR;
323 }
324 return parcel->msgParcel->Append(*(data->msgParcel)) ? OH_IPC_SUCCESS : OH_IPC_PARCEL_WRITE_ERROR;
325 }
326
OH_IPCParcel_WriteInterfaceToken(OHIPCParcel * parcel,const char * token)327 int OH_IPCParcel_WriteInterfaceToken(OHIPCParcel *parcel, const char *token)
328 {
329 if (!IsIPCParcelValid(parcel, __func__) || token == nullptr) {
330 return OH_IPC_CHECK_PARAM_ERROR;
331 }
332
333 int tokenLen = strlen(token);
334 if (tokenLen == 0 || tokenLen > MAX_PARCEL_LEN) {
335 return OH_IPC_CHECK_PARAM_ERROR;
336 }
337 std::u16string u16Token = OHOS::Str8ToStr16(std::string(token, tokenLen));
338 if (u16Token.length() == 0 && tokenLen != 0) {
339 ZLOGE(LOG_LABEL, "convert token to u16string failed: %{public}d", tokenLen);
340 return OH_IPC_PARCEL_WRITE_ERROR;
341 }
342 size_t writePosition = parcel->msgParcel->GetWritePosition();
343 if (!parcel->msgParcel->WriteInterfaceToken(u16Token)) {
344 ZLOGE(LOG_LABEL, "WriteInterfaceToken failed! token len:%{public}d", tokenLen);
345 parcel->msgParcel->RewindWrite(writePosition);
346 return OH_IPC_PARCEL_WRITE_ERROR;
347 }
348 return OH_IPC_SUCCESS;
349 }
350
OH_IPCParcel_ReadInterfaceToken(const OHIPCParcel * parcel,char ** token,int32_t * len,OH_IPC_MemAllocator allocator)351 int OH_IPCParcel_ReadInterfaceToken(const OHIPCParcel *parcel, char **token, int32_t *len,
352 OH_IPC_MemAllocator allocator)
353 {
354 if (!IsIPCParcelValid(parcel, __func__) || !IsMemoryParamsValid(token, len, allocator, __func__)) {
355 return OH_IPC_CHECK_PARAM_ERROR;
356 }
357 size_t readPosition = parcel->msgParcel->GetReadPosition();
358 std::u16string u16Token = parcel->msgParcel->ReadInterfaceToken();
359 std::string strToken = OHOS::Str16ToStr8(u16Token);
360 if (u16Token.length() != 0 && strToken.length() == 0) {
361 parcel->msgParcel->RewindRead(readPosition);
362 ZLOGE(LOG_LABEL, "Str16ToStr8 failed! u16Token len: %{public}u, string len: %{public}u",
363 static_cast<uint32_t>(u16Token.length()), static_cast<uint32_t>(strToken.length()));
364 return OH_IPC_PARCEL_READ_ERROR;
365 }
366
367 int memLength = static_cast<int>(strToken.length()) + 1;
368 *token = static_cast<char*>(allocator(memLength));
369 if (*token == nullptr) {
370 parcel->msgParcel->RewindRead(readPosition);
371 ZLOGE(LOG_LABEL, "memory allocator failed!");
372 return OH_IPC_MEM_ALLOCATOR_ERROR;
373 }
374 if (memcpy_s(*token, memLength, strToken.c_str(), memLength) != EOK) {
375 parcel->msgParcel->RewindRead(readPosition);
376 ZLOGE(LOG_LABEL, "memcpy string failed, string len: %{public}d", memLength);
377 return OH_IPC_PARCEL_READ_ERROR;
378 }
379 *len = memLength;
380 return OH_IPC_SUCCESS;
381 }
382