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