• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <libmtp.h>
16 #include "libmtp_fuzzer.h"
17 
18 #include <cstddef>
19 #include <cstdint>
20 #include <algorithm>
21 
22 namespace OHOS {
23 constexpr size_t MIN_STORAGE_SIZE = sizeof(uint16_t) * 3 + sizeof(uint32_t) + sizeof(uint64_t) * 3 + sizeof(char *) * 2;
24 constexpr size_t MIN_EXTENSION_SIZE = sizeof(char *) + sizeof(int) * 2;
25 constexpr size_t MIN_MTPDEVICE_SIZE = sizeof(uint8_t) * 2 + sizeof(uint32_t) * 8 + sizeof(int);
26 constexpr size_t MIN_SIZE = std::max({MIN_STORAGE_SIZE, MIN_EXTENSION_SIZE, MIN_MTPDEVICE_SIZE});
27 constexpr size_t MIN_RAWDEVICE_SIZE = sizeof(uint32_t) * 2 + sizeof(uint16_t) * 2 +
28                                       sizeof(uint8_t) + sizeof(int) + sizeof(char *) * 2;
29 constexpr size_t MIN_FOLDER_SIZE = sizeof(uint32_t) * 3 + sizeof(char *);
30 constexpr size_t MIN_FILE_SIZE = sizeof(uint32_t) * 3 + sizeof(uint64_t) + sizeof(char *) +
31                                  sizeof(time_t) + sizeof(LIBMTP_filetype_t);
32 
33 template<class T>
TypeCast(const uint8_t * data,int * pos=nullptr)34 T TypeCast(const uint8_t *data, int *pos = nullptr)
35 {
36     if (pos) {
37         *pos += sizeof(T);
38     }
39     return *(reinterpret_cast<const T*>(data));
40 }
41 
ConstructRawDevice(const uint8_t * data,size_t size,LIBMTP_device_entry_t * entry,LIBMTP_raw_device_t * device)42 int ConstructRawDevice(const uint8_t *data, size_t size, LIBMTP_device_entry_t *entry, LIBMTP_raw_device_t *device)
43 {
44     int pos = 0;
45     if (entry != nullptr) {
46         entry->vendor = TypeCast<char*>(data, &pos);
47         entry->product = TypeCast<char*>(data + pos);
48         entry->vendor_id = TypeCast<uint16_t>(data + pos);
49         entry->product_id = TypeCast<uint16_t>(data + pos);
50         entry->device_flags = TypeCast<uint32_t>(data + pos);
51         device->bus_location = TypeCast<uint32_t>(data + pos);
52         device->devnum = TypeCast<uint8_t>(data + pos);
53         device->device_entry = *entry;
54     }
55     return pos;
56 }
57 
ConstructDeviceStorage(const uint8_t * data,size_t size,LIBMTP_devicestorage_t * storage)58 void ConstructDeviceStorage(const uint8_t *data, size_t size, LIBMTP_devicestorage_t *storage)
59 {
60     int pos = 0;
61     if (storage != nullptr) {
62         storage->id = TypeCast<uint32_t>(data, &pos);
63         storage->StorageType = TypeCast<uint16_t>(data + pos);
64         storage->FilesystemType = TypeCast<uint16_t>(data + pos);
65         storage->AccessCapability = TypeCast<uint16_t>(data + pos);
66         storage->MaxCapacity = TypeCast<uint64_t>(data + pos);
67         storage->FreeSpaceInBytes = TypeCast<uint64_t>(data + pos);
68         storage->FreeSpaceInObjects = TypeCast<uint64_t>(data + pos);
69         storage->StorageDescription = TypeCast<char*>(data + pos);
70         storage->VolumeIdentifier = TypeCast<char*>(data + pos);
71         storage->next = nullptr;
72         storage->prev = nullptr;
73     }
74 }
75 
ConstructDeviceExtension(const uint8_t * data,size_t size,LIBMTP_device_extension_t * extensions)76 void ConstructDeviceExtension(const uint8_t *data, size_t size, LIBMTP_device_extension_t *extensions)
77 {
78     int pos = 0;
79     if (extensions != nullptr) {
80         extensions->name = TypeCast<char*>(data + pos);
81         extensions->major = TypeCast<int>(data + pos);
82         extensions->minor = TypeCast<int>(data + pos);
83         extensions->next = nullptr;
84     }
85 }
86 
ConstructMtpDevice(const uint8_t * data,size_t size,LIBMTP_mtpdevice_t * device)87 int ConstructMtpDevice(const uint8_t *data, size_t size, LIBMTP_mtpdevice_t *device)
88 {
89     if (data == nullptr || size <= MIN_SIZE) {
90         return 0;
91     }
92     LIBMTP_devicestorage_t storage;
93     LIBMTP_device_extension_t extensions;
94     LIBMTP_error_t errorStack;
95 
96     int pos = 0;
97     if (device == nullptr) {
98         return 0;
99     }
100     device->object_bitsize = TypeCast<uint8_t>(data, &pos);
101     ConstructDeviceStorage(data, size, &storage);
102     device->storage = &storage;
103     errorStack = TypeCast<LIBMTP_error_t>(data + pos);
104     device->errorstack = &errorStack;
105     device->maximum_battery_level = TypeCast<uint8_t>(data + pos);
106     device->default_music_folder = TypeCast<uint32_t>(data + pos);
107     device->default_playlist_folder = TypeCast<uint32_t>(data + pos);
108     device->default_picture_folder = TypeCast<uint32_t>(data + pos);
109     device->default_video_folder = TypeCast<uint32_t>(data + pos);
110     device->default_organizer_folder = TypeCast<uint32_t>(data + pos);
111     device->default_zencast_folder = TypeCast<uint32_t>(data + pos);
112     device->default_album_folder = TypeCast<uint32_t>(data + pos);
113     device->default_text_folder = TypeCast<uint32_t>(data + pos);
114     ConstructDeviceExtension(data, size, &extensions);
115     device->extensions = &extensions;
116     device->cached = TypeCast<int>(data + pos);
117     device->next = nullptr;
118 
119     return pos;
120 }
121 
ConstructFolder(const uint8_t * data,size_t size,int pos,LIBMTP_folder_t * folder)122 int ConstructFolder(const uint8_t *data, size_t size, int pos, LIBMTP_folder_t *folder)
123 {
124     if (folder != nullptr) {
125         folder->folder_id = TypeCast<uint32_t>(data + pos);
126         folder->parent_id = TypeCast<uint32_t>(data + pos);
127         folder->storage_id = TypeCast<uint32_t>(data + pos);
128         folder->name = TypeCast<char*>(data + pos);
129         folder->sibling = nullptr;
130         folder->child = nullptr;
131     }
132 }
133 
ConstructFile(const uint8_t * data,size_t size,int pos,LIBMTP_file_t * file)134 int ConstructFile(const uint8_t *data, size_t size, int pos, LIBMTP_file_t *file)
135 {
136     if (file != nullptr) {
137         file->item_id = TypeCast<uint32_t>(data + pos);
138         file->parent_id = TypeCast<uint32_t>(data + pos);
139         file->storage_id = TypeCast<uint32_t>(data + pos);
140         file->filename = TypeCast<char*>(data + pos);
141         file->filesize = TypeCast<uint64_t>(data + pos);
142         file->modificationdate = TypeCast<time_t>(data + pos);
143         file->filetype = TypeCast<LIBMTP_filetype_t>(data + pos);
144         file->next = nullptr;
145     }
146 }
147 
CheckSpecificDeviceFuzzTest(const uint8_t * data,size_t size)148 bool CheckSpecificDeviceFuzzTest(const uint8_t *data, size_t size)
149 {
150     int numPara32 = 2;
151     if (data == nullptr || size <= sizeof(int) * numPara32) {
152         return false;
153     }
154 
155     int pos = 0;
156     int busno = TypeCast<int>(data, &pos);
157     int devno = TypeCast<int>(data + pos);
158 
159     LIBMTP_Check_Specific_Device(busno, devno);
160     return true;
161 }
162 
OpenRawDeviceUncachedTest(const uint8_t * data,size_t size)163 bool OpenRawDeviceUncachedTest(const uint8_t *data, size_t size)
164 {
165     if (data == nullptr || size <= MIN_RAWDEVICE_SIZE) {
166         return false;
167     }
168 
169     LIBMTP_device_entry_t entry;
170     LIBMTP_raw_device_t device;
171     ConstructRawDevice(data, size, &entry, &device);
172 
173     LIBMTP_mtpdevice_t *ret = LIBMTP_Open_Raw_Device_Uncached(&device);
174     if (ret == NULL) {
175         return false;
176     }
177     return true;
178 }
179 
DetectRawDevicesTest(const uint8_t * data,size_t size)180 bool DetectRawDevicesTest(const uint8_t *data, size_t size)
181 {
182     if (data == nullptr || size <= MIN_RAWDEVICE_SIZE) {
183         return false;
184     }
185 
186     LIBMTP_device_entry_t entry;
187     LIBMTP_raw_device_t *device;
188     int pos = ConstructRawDevice(data, size, &entry, device);
189     int numdevs = TypeCast<int>(data + pos);
190 
191     LIBMTP_error_number_t result = LIBMTP_Detect_Raw_Devices(&device, &numdevs);
192     if (result != 0) {
193         return false;
194     }
195     return true;
196 }
197 
ReleaseDeviceTest(const uint8_t * data,size_t size)198 bool ReleaseDeviceTest(const uint8_t *data, size_t size)
199 {
200     if (data == nullptr || size <= MIN_SIZE) {
201         return false;
202     }
203     LIBMTP_mtpdevice_t mtpDevice;
204     int ret = ConstructMtpDevice(data, size, &mtpDevice);
205     LIBMTP_Release_Device(&mtpDevice);
206     return true;
207 }
208 
GetFilesAndFoldersTest(const uint8_t * data,size_t size)209 bool GetFilesAndFoldersTest(const uint8_t *data, size_t size)
210 {
211     int numPara32 = 2;
212     if (data == nullptr || size <= MIN_SIZE + sizeof(uint32_t) * numPara32) {
213         return false;
214     }
215     LIBMTP_mtpdevice_t mtpDevice;
216     int pos = ConstructMtpDevice(data, size, &mtpDevice);
217     uint32_t storage = TypeCast<uint32_t>(data + pos);
218     uint32_t parent = TypeCast<uint32_t>(data + pos);
219     LIBMTP_file_t *ret = LIBMTP_Get_Files_And_Folders(&mtpDevice, storage, parent);
220     if (ret == NULL) {
221         return false;
222     }
223     return true;
224 }
225 
CreateFolderTest(const uint8_t * data,size_t size)226 bool CreateFolderTest(const uint8_t *data, size_t size)
227 {
228     int numPara32 = 2;
229     if (data == nullptr || size <= MIN_SIZE + sizeof(uint32_t) * numPara32 + sizeof(char*)) {
230         return false;
231     }
232     LIBMTP_mtpdevice_t mtpDevice;
233     int pos = ConstructMtpDevice(data, size, &mtpDevice);
234     char* name = TypeCast<char*>(data + pos);
235     uint32_t parentId = TypeCast<uint32_t>(data + pos);
236     uint32_t storageId = TypeCast<uint32_t>(data + pos);
237     uint32_t ret = LIBMTP_Create_Folder(&mtpDevice, name, parentId, storageId);
238     if (ret == 0) {
239         return false;
240     }
241     return true;
242 }
243 
SetFolderNameTest(const uint8_t * data,size_t size)244 bool SetFolderNameTest(const uint8_t *data, size_t size)
245 {
246     if (data == nullptr || size <= MIN_SIZE + MIN_FOLDER_SIZE + sizeof(char*)) {
247         return false;
248     }
249     LIBMTP_mtpdevice_t mtpDevice;
250     LIBMTP_folder_t folder;
251     int pos = ConstructMtpDevice(data, size, &mtpDevice);
252     pos = ConstructFolder(data, size, pos, &folder);
253     char* newName = TypeCast<char*>(data + pos);
254     uint32_t ret = LIBMTP_Set_Folder_Name(&mtpDevice, &folder, newName);
255     if (ret != 0) {
256         return false;
257     }
258     return true;
259 }
260 
GetFileToFileTest(const uint8_t * data,size_t size)261 bool GetFileToFileTest(const uint8_t *data, size_t size)
262 {
263     if (data == nullptr || size <= MIN_SIZE + sizeof(uint32_t) + sizeof(LIBMTP_progressfunc_t)
264         + sizeof(char const *const) + sizeof(void const *const)) {
265         return false;
266     }
267     LIBMTP_mtpdevice_t mtpDevice;
268 
269     int pos = ConstructMtpDevice(data, size, &mtpDevice);
270     uint32_t id = TypeCast<uint32_t>(data + pos);
271     char const *const path = TypeCast<char const *const>(data + pos);
272     LIBMTP_progressfunc_t const callback = TypeCast<LIBMTP_progressfunc_t const>(data + pos);
273     void const * const userData = TypeCast<void const * const>(data + pos);
274 
275     int ret = LIBMTP_Get_File_To_File(&mtpDevice, id, path, callback, userData);
276     if (ret != 0) {
277         return false;
278     }
279     return true;
280 }
281 
SendFileFromFileTest(const uint8_t * data,size_t size)282 bool SendFileFromFileTest(const uint8_t *data, size_t size)
283 {
284     if (data == nullptr || size <= MIN_SIZE + MIN_FILE_SIZE + sizeof(LIBMTP_progressfunc_t)
285         + sizeof(char const *const) + sizeof(void const *const)) {
286         return false;
287     }
288     LIBMTP_mtpdevice_t mtpDevice;
289     LIBMTP_file_t file;
290     int pos = ConstructMtpDevice(data, size, &mtpDevice);
291     char const *const path = TypeCast<char const *const>(data + pos);
292     pos = ConstructFile(data, size, pos, &file);
293     LIBMTP_progressfunc_t const callback = TypeCast<LIBMTP_progressfunc_t const>(data + pos);
294     void const * const userData = TypeCast<void const * const>(data + pos);
295 
296     int ret = LIBMTP_Send_File_From_File(&mtpDevice, path, &file, callback, userData);
297     if (ret != 0) {
298         return false;
299     }
300     return true;
301 }
302 
SetFileNameTest(const uint8_t * data,size_t size)303 bool SetFileNameTest(const uint8_t *data, size_t size)
304 {
305     if (data == nullptr || size <= MIN_SIZE + MIN_FILE_SIZE + sizeof(const char*)) {
306         return false;
307     }
308     LIBMTP_mtpdevice_t mtpDevice;
309     LIBMTP_file_t file;
310     int pos = ConstructMtpDevice(data, size, &mtpDevice);
311     pos = ConstructFile(data, size, pos, &file);
312     char *newName = TypeCast<char *>(data + pos);
313 
314     int ret = LIBMTP_Set_File_Name(&mtpDevice, &file, newName);
315     if (ret != 0) {
316         return false;
317     }
318     return true;
319 }
320 
DeleteObjectTest(const uint8_t * data,size_t size)321 bool DeleteObjectTest(const uint8_t *data, size_t size)
322 {
323     if (data == nullptr || size <= MIN_SIZE + sizeof(uint32_t)) {
324         return false;
325     }
326     LIBMTP_mtpdevice_t mtpDevice;
327     int pos = ConstructMtpDevice(data, size, &mtpDevice);
328     uint32_t objectId = TypeCast<uint32_t>(data + pos);
329 
330     int ret = LIBMTP_Delete_Object(&mtpDevice, objectId);
331     if (ret != 0) {
332         return false;
333     }
334     return true;
335 }
336 
SetObjectU32Test(const uint8_t * data,size_t size)337 bool SetObjectU32Test(const uint8_t *data, size_t size)
338 {
339     int numPara32 = 2;
340     if (data == nullptr || size <= MIN_SIZE + sizeof(uint32_t const) * numPara32 + sizeof(LIBMTP_property_t const)) {
341         return false;
342     }
343     LIBMTP_mtpdevice_t mtpDevice;
344     int pos = ConstructMtpDevice(data, size, &mtpDevice);
345     uint32_t const objectId = TypeCast<uint32_t const>(data + pos);
346     LIBMTP_property_t const attributeId = TypeCast<LIBMTP_property_t const>(data + pos);
347     uint32_t const value = TypeCast<uint32_t const>(data + pos);
348 
349     int ret = LIBMTP_Set_Object_u32(&mtpDevice, objectId, attributeId, value);
350     if (ret != 0) {
351         return false;
352     }
353     return true;
354 }
355 
SetObjectStringTest(const uint8_t * data,size_t size)356 bool SetObjectStringTest(const uint8_t *data, size_t size)
357 {
358     if (data == nullptr || size <= MIN_SIZE + sizeof(uint32_t const) +
359         sizeof(LIBMTP_property_t const) + sizeof(char const *const)) {
360         return false;
361     }
362     LIBMTP_mtpdevice_t mtpDevice;
363     int pos = ConstructMtpDevice(data, size, &mtpDevice);
364     uint32_t const objectId = TypeCast<uint32_t const>(data + pos);
365     LIBMTP_property_t const attributeId = TypeCast<LIBMTP_property_t const>(data + pos);
366     char const * const string = TypeCast<char const * const>(data + pos);
367 
368     int ret = LIBMTP_Set_Object_String(&mtpDevice, objectId, attributeId, string);
369     if (ret != 0) {
370         return false;
371     }
372     return true;
373 }
374 
GetPartialObjectTest(const uint8_t * data,size_t size)375 bool GetPartialObjectTest(const uint8_t *data, size_t size)
376 {
377     int numPara32 = 2;
378     size_t sizeReq = MIN_SIZE + sizeof(uint32_t const) * numPara32 +
379                      sizeof(uint64_t const) + sizeof(unsigned int) + sizeof(unsigned char*);
380     if (data == nullptr || size <= sizeReq) {
381         return false;
382     }
383     LIBMTP_mtpdevice_t mtpDevice;
384     int pos = ConstructMtpDevice(data, size, &mtpDevice);
385     uint32_t const id = TypeCast<uint32_t const>(data + pos);
386     uint64_t offset = TypeCast<uint64_t>(data + pos);
387     uint32_t maxbytes = TypeCast<uint32_t>(data + pos);
388     unsigned char* paraData = TypeCast<unsigned char*>(data + pos);
389     unsigned int paraSize = TypeCast<unsigned int>(data + pos);
390 
391     int ret = LIBMTP_GetPartialObject(&mtpDevice, id, offset, maxbytes, &paraData, &paraSize);
392     if (ret == -1) {
393         return false;
394     }
395     return true;
396 }
397 
SendPartialObjectTest(const uint8_t * data,size_t size)398 bool SendPartialObjectTest(const uint8_t *data, size_t size)
399 {
400     size_t sizeReq = MIN_SIZE + sizeof(uint32_t const) + sizeof(uint64_t const) +
401                      sizeof(unsigned int) + sizeof(unsigned char);
402     if (data == nullptr || size <= sizeReq) {
403         return false;
404     }
405     LIBMTP_mtpdevice_t mtpDevice;
406     int pos = ConstructMtpDevice(data, size, &mtpDevice);
407     uint32_t const id = TypeCast<uint32_t const>(data + pos);
408     uint64_t offset = TypeCast<uint64_t>(data + pos);
409     unsigned char paraData = TypeCast<unsigned char>(data + pos);
410     unsigned int paraSize = TypeCast<unsigned int>(data + pos);
411 
412     int ret = LIBMTP_SendPartialObject(&mtpDevice, id, offset, &paraData, paraSize);
413     if (ret == -1) {
414         return false;
415     }
416     return true;
417 }
418 
GetStorageTest(const uint8_t * data,size_t size)419 bool GetStorageTest(const uint8_t *data, size_t size)
420 {
421     if (data == nullptr || size <= MIN_SIZE + sizeof(int)) {
422         return false;
423     }
424     LIBMTP_mtpdevice_t mtpDevice;
425     int pos = ConstructMtpDevice(data, size, &mtpDevice);
426     int sortby = TypeCast<int>(data + pos);
427     int ret = LIBMTP_Get_Storage(&mtpDevice, sortby);
428     if (ret == -1) {
429         return false;
430     }
431     return true;
432 }
433 
CheckCapabilityTest(const uint8_t * data,size_t size)434 bool CheckCapabilityTest(const uint8_t *data, size_t size)
435 {
436     if (data == nullptr || size <= MIN_SIZE) {
437         return false;
438     }
439     LIBMTP_mtpdevice_t mtpDevice;
440     LIBMTP_devicecap_t cap;
441     ConstructMtpDevice(data, size, &mtpDevice);
442     if (&mtpDevice == NULL || mtpDevice.params == NULL) {
443         return true;
444     } else {
445         cap = LIBMTP_DEVICECAP_GetPartialObject;
446         LIBMTP_Check_Capability(&mtpDevice, cap);
447         cap = LIBMTP_DEVICECAP_SendPartialObject;
448         LIBMTP_Check_Capability(&mtpDevice, cap);
449         cap = LIBMTP_DEVICECAP_EditObjects;
450         LIBMTP_Check_Capability(&mtpDevice, cap);
451         cap = LIBMTP_DEVICECAP_MoveObject;
452         LIBMTP_Check_Capability(&mtpDevice, cap);
453         cap = LIBMTP_DEVICECAP_CopyObject;
454         LIBMTP_Check_Capability(&mtpDevice, cap);
455     }
456     return true;
457 }
458 
DumpErrorstackTest(const uint8_t * data,size_t size)459 bool DumpErrorstackTest(const uint8_t *data, size_t size)
460 {
461     if (data == nullptr || size <= MIN_SIZE) {
462         return false;
463     }
464     LIBMTP_mtpdevice_t mtpDevice;
465     ConstructMtpDevice(data, size, &mtpDevice);
466     LIBMTP_Dump_Errorstack(&mtpDevice);
467     return true;
468 }
469 
ClearErrorstackTest(const uint8_t * data,size_t size)470 bool ClearErrorstackTest(const uint8_t *data, size_t size)
471 {
472     if (data == nullptr || size <= MIN_SIZE) {
473         return false;
474     }
475     LIBMTP_mtpdevice_t mtpDevice;
476     ConstructMtpDevice(data, size, &mtpDevice);
477     LIBMTP_Clear_Errorstack(&mtpDevice);
478     return true;
479 }
480 } // namespace OHOS
481 
482 /* Fuzzer entry point */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)483 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
484 {
485     /* Run your code on data */
486     OHOS::CheckSpecificDeviceFuzzTest(data, size);
487     OHOS::OpenRawDeviceUncachedTest(data, size);
488     OHOS::DetectRawDevicesTest(data, size);
489     OHOS::ReleaseDeviceTest(data, size);
490     OHOS::GetFilesAndFoldersTest(data, size);
491     OHOS::CreateFolderTest(data, size);
492     OHOS::SetFolderNameTest(data, size);
493     OHOS::GetFileToFileTest(data, size);
494     OHOS::SendFileFromFileTest(data, size);
495     OHOS::SetFileNameTest(data, size);
496     OHOS::DeleteObjectTest(data, size);
497     OHOS::SetObjectU32Test(data, size);
498     OHOS::SetObjectStringTest(data, size);
499     OHOS::GetPartialObjectTest(data, size);
500     OHOS::SendPartialObjectTest(data, size);
501     OHOS::GetStorageTest(data, size);
502     OHOS::CheckCapabilityTest(data, size);
503     OHOS::DumpErrorstackTest(data, size);
504     OHOS::ClearErrorstackTest(data, size);
505     return 0;
506 }