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