/* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include using namespace android; constexpr uint16_t kFeasibleTypes[] = { MTP_TYPE_UNDEFINED, MTP_TYPE_INT8, MTP_TYPE_UINT8, MTP_TYPE_INT16, MTP_TYPE_UINT16, MTP_TYPE_INT32, MTP_TYPE_UINT32, MTP_TYPE_INT64, MTP_TYPE_UINT64, MTP_TYPE_INT128, MTP_TYPE_UINT128, MTP_TYPE_AINT8, MTP_TYPE_AUINT8, MTP_TYPE_AINT16, MTP_TYPE_AUINT16, MTP_TYPE_AINT32, MTP_TYPE_AUINT32, MTP_TYPE_AINT64, MTP_TYPE_AUINT64, MTP_TYPE_AINT128, MTP_TYPE_AUINT128, MTP_TYPE_STR, }; class MtpPropertyFuzzer : MtpPacketFuzzerUtils { public: MtpPropertyFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) { mUsbDevFsUrb = (struct usbdevfs_urb*)malloc(sizeof(struct usbdevfs_urb) + sizeof(struct usbdevfs_iso_packet_desc)); }; ~MtpPropertyFuzzer() { free(mUsbDevFsUrb); }; void process(); private: FuzzedDataProvider mFdp; }; void MtpPropertyFuzzer::process() { MtpProperty* mtpProperty = nullptr; if (mFdp.ConsumeBool()) { mtpProperty = new MtpProperty(); } else { uint16_t type = mFdp.ConsumeBool() ? mFdp.ConsumeIntegral() : mFdp.PickValueInArray(kFeasibleTypes); mtpProperty = new MtpProperty(mFdp.ConsumeIntegral(), type, mFdp.ConsumeBool(), mFdp.ConsumeIntegral()); } while (mFdp.remaining_bytes() > 0) { auto invokeMtpPropertyFuzzer = mFdp.PickValueInArray>({ [&]() { MtpDataPacket mtpDataPacket; if (mFdp.ConsumeBool()) { mtpProperty->read(mtpDataPacket); } else { if (mFdp.ConsumeBool()) { #ifdef MTP_DEVICE android::IMtpHandle* h = new MtpDevHandle(); h->start(mFdp.ConsumeBool()); std::string text = mFdp.ConsumeRandomLengthString(kMaxLength); char* data = const_cast(text.c_str()); h->read(static_cast(data), text.length()); mtpDataPacket.write(h); h->close(); delete h; #endif #ifdef MTP_HOST fillFilePath(&mFdp); int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING); fillUsbRequest(fd, &mFdp); mUsbRequest.dev = usb_device_new(mPath.c_str(), fd); mtpDataPacket.write(&mUsbRequest, mFdp.PickValueInArray( kUrbPacketDivisionModes), fd, mFdp.ConsumeIntegralInRange(kMinSize, kMaxSize)); usb_device_close(mUsbRequest.dev); #endif } if (mFdp.ConsumeBool()) { mtpProperty->write(mtpDataPacket); } else { mtpProperty->setCurrentValue(mtpDataPacket); } } }, [&]() { char16_t* data = nullptr; std::string str = mFdp.ConsumeRandomLengthString(kMaxLength); android::String16 s(str.c_str()); if (mFdp.ConsumeBool()) { data = const_cast(s.c_str()); } if (mFdp.ConsumeBool()) { mtpProperty->setDefaultValue(reinterpret_cast(data)); } else if (mFdp.ConsumeBool()) { mtpProperty->setCurrentValue(reinterpret_cast(data)); } else { mtpProperty->setCurrentValue(str.c_str()); } }, [&]() { mtpProperty->setFormRange(mFdp.ConsumeIntegral(), mFdp.ConsumeIntegral(), mFdp.ConsumeIntegral()); }, [&]() { std::vector init; for (size_t idx = 0; idx < mFdp.ConsumeIntegralInRange(kMinSize, kMaxSize); ++idx) { init.push_back(mFdp.ConsumeIntegral()); } mtpProperty->setFormEnum(init.data(), init.size()); }, }); invokeMtpPropertyFuzzer(); } delete (mtpProperty); } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { MtpPropertyFuzzer mtpPropertyFuzzer(data, size); mtpPropertyFuzzer.process(); return 0; }