diff --git a/frameworks/innerkitsimpl/test/fuzztest/BUILD.gn b/frameworks/innerkitsimpl/test/fuzztest/BUILD.gn index 5a21f6f4bd27592ff52212478c405ce657876873..ff4d013c41fa5a6e41f6b44fac1622769e9ce3c2 100644 --- a/frameworks/innerkitsimpl/test/fuzztest/BUILD.gn +++ b/frameworks/innerkitsimpl/test/fuzztest/BUILD.gn @@ -24,6 +24,7 @@ group("fuzztest") { "imagefwkdecodepicture_fuzzer:ImageFwkDecodePictureFuzzTest", "imagefwkimagesource_fuzzer:ImageFwkImageSourceFuzzTest", "imagefwkimagesource2_fuzzer:ImageFwkImageSource2FuzzTest", + "imagefwkimagesource3_fuzzer:ImageFwkImageSource3FuzzTest", "imagegifencoder_fuzzer:ImageGifEnCoderFuzzTest", "imageheifimpl_fuzzer:ImageHeifImplFuzzTest", "imageheifimpl2_fuzzer:ImageHeifImpl2FuzzTest", diff --git a/frameworks/innerkitsimpl/test/fuzztest/imagefwkimagesource3_fuzzer/BUILD.gn b/frameworks/innerkitsimpl/test/fuzztest/imagefwkimagesource3_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..da8ba29312e1a891606f9467e03325c1fdd4c48b --- /dev/null +++ b/frameworks/innerkitsimpl/test/fuzztest/imagefwkimagesource3_fuzzer/BUILD.gn @@ -0,0 +1,48 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# 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. + +import("//build/test.gni") +import("//foundation/multimedia/image_framework/ide/image_decode_config.gni") + +ohos_fuzztest("ImageFwkImageSource3FuzzTest") { + module_out_path = "image_framework/image_framework" + fuzz_config_file = "$image_subsystem/frameworks/innerkitsimpl/test/fuzztest/imagefwkimagesource3_fuzzer" + resource_config_file = "$image_subsystem/test/resource/image/ohos_test.xml" + + include_dirs = [ + "./include", + "$image_subsystem/frameworks/innerkitsimpl/utils/include", + "$image_subsystem/frameworks/innerkitsimpl/test/fuzztest/common/include", + ] + + sources = [ + "$image_subsystem/frameworks/innerkitsimpl/test/fuzztest/common/src/common_fuzztest_function.cpp", + "src/image_fwk_image_source3_fuzzer.cpp", + ] + + deps = [ + "$image_subsystem/frameworks/innerkitsimpl/utils:image_utils", + "$image_subsystem/interfaces/innerkits:image_native", + ] + + external_deps = [ + "c_utils:utils", + "graphic_2d:color_manager", + "hilog:libhilog", + ] + + cflags = [ + "-Dprotected=public", + "-Dprivate=public", + ] +} diff --git a/frameworks/innerkitsimpl/test/fuzztest/imagefwkimagesource3_fuzzer/corpus/init b/frameworks/innerkitsimpl/test/fuzztest/imagefwkimagesource3_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..14cddafc02dab1563ad53641643adc8357882071 --- /dev/null +++ b/frameworks/innerkitsimpl/test/fuzztest/imagefwkimagesource3_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * 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. + */ + +FUZZ diff --git a/frameworks/innerkitsimpl/test/fuzztest/imagefwkimagesource3_fuzzer/include/image_fwk_image_source3_fuzzer.h b/frameworks/innerkitsimpl/test/fuzztest/imagefwkimagesource3_fuzzer/include/image_fwk_image_source3_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..6133d4ac56f0772362c47baa13de4334ddd70299 --- /dev/null +++ b/frameworks/innerkitsimpl/test/fuzztest/imagefwkimagesource3_fuzzer/include/image_fwk_image_source3_fuzzer.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * 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. + */ +#ifndef IMAGE_FWK_IMAGE_SOURCE_THREE_FUZZER_H +#define IMAGE_FWK_IMAGE_SOURCE_THREE_FUZZER_H + +#define FUZZ_PROJECT_NAME "image_fwk_image_source_three_fuzzer" +#endif diff --git a/frameworks/innerkitsimpl/test/fuzztest/imagefwkimagesource3_fuzzer/project.xml b/frameworks/innerkitsimpl/test/fuzztest/imagefwkimagesource3_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..9957c34a73efcd24e67dc21af78a2c24fe0f9ce6 --- /dev/null +++ b/frameworks/innerkitsimpl/test/fuzztest/imagefwkimagesource3_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 15728640 + + 300 + + 4096 + + diff --git a/frameworks/innerkitsimpl/test/fuzztest/imagefwkimagesource3_fuzzer/src/image_fwk_image_source3_fuzzer.cpp b/frameworks/innerkitsimpl/test/fuzztest/imagefwkimagesource3_fuzzer/src/image_fwk_image_source3_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..77cae12a5f7c190088a7ed9dad36fd00da2b6d90 --- /dev/null +++ b/frameworks/innerkitsimpl/test/fuzztest/imagefwkimagesource3_fuzzer/src/image_fwk_image_source3_fuzzer.cpp @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * 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 "image_fwk_image_source3_fuzzer.h" + +#include +#include +#include +#include +#include +#include "common_fuzztest_function.h" + +#include "image_dfx.h" +#include "image_log.h" +#include "image_packer.h" +#include "image_source.h" +#include "image_utils.h" +#include "media_errors.h" + +namespace OHOS { +namespace Media { +FuzzedDataProvider *FDP; + +namespace { + static constexpr uint32_t MAX_SOURCE_SIZE = 300 * 1024 * 1024; + static constexpr uint32_t PIXELFORMAT_MODULO = 105; + static constexpr uint32_t SOURCEOPTIONS_MIMETYPE_MODULO = 3; + static constexpr uint32_t ALLOCATOR_TYPE_MODULO = 5; + static constexpr uint32_t DECODE_DYNAMIC_RANGE_MODULO = 3; + static constexpr uint32_t INCREMENTAL_MODE_MODULO = 2; + static constexpr uint32_t INCREMENTAL_DECODING_STATE_MODULO = 7; + static constexpr uint32_t SOURCE_DECODING_STATE_MODULO = 9; + static constexpr uint32_t AUXILIARY_PICTURE_TYPE_MODULO = 6; +} + +std::unique_ptr ConstructImageSourceByBuffer(const uint8_t *data, size_t size) +{ + SourceOptions opts; + std::string mimeType[] = {"image/jpeg", "image/heic", "image/heif"}; + opts.formatHint = mimeType[FDP->ConsumeIntegral() % SOURCEOPTIONS_MIMETYPE_MODULO]; + opts.pixelFormat = static_cast(FDP->ConsumeIntegral() % PIXELFORMAT_MODULO); + size_t power = FDP->ConsumeIntegralInRange(0, 10); + int32_t height = std::pow(2, power); + if (static_cast(height) > size) { + return nullptr; + } + int32_t width = static_cast(size / static_cast(height)); + if (static_cast(width * height) != size) { + return nullptr; + } + opts.size.height = height; + opts.size.width = width; + uint32_t errorCode { 0 }; + return ImageSource::CreateImageSource(data, size, opts, errorCode); +} + +std::unique_ptr ConstructImageSourceByFd(const uint8_t *data, size_t size) +{ + std::string pathName = "/data/local/tmp/test_create_imagesource_pathname.png"; + if (!WriteDataToFile(data, size, pathName)) { + return nullptr; + } + int fd = open(pathName.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + if (fd < 0) { + return nullptr; + } + SourceOptions opts; + std::string mimeType[] = {"image/jpeg", "image/heic", "image/heif"}; + opts.formatHint = mimeType[FDP->ConsumeIntegral() % SOURCEOPTIONS_MIMETYPE_MODULO]; + opts.pixelFormat = static_cast(FDP->ConsumeIntegral() % PIXELFORMAT_MODULO); + size_t power = FDP->ConsumeIntegralInRange(0, 10); + int32_t height = std::pow(2, power); + if (static_cast(height) > size) { + return nullptr; + } + int32_t width = static_cast(size / static_cast(height)); + if (static_cast(width * height) != size) { + return nullptr; + } + opts.size.height = height; + opts.size.width = width; + uint32_t errorCode { 0 }; + return ImageSource::CreateImageSource(fd, opts, errorCode); +} + +std::unique_ptr ConstructImageSourceByPath(const uint8_t *data, size_t size) +{ + std::string pathName = "/data/local/tmp/test_create_imagesource_pathname.png"; + if (!WriteDataToFile(data, size, pathName)) { + return nullptr; + } + SourceOptions opts; + std::string mimeType[] = {"image/jpeg", "image/heic", "image/heif"}; + opts.formatHint = mimeType[FDP->ConsumeIntegral() % SOURCEOPTIONS_MIMETYPE_MODULO]; + opts.pixelFormat = static_cast(FDP->ConsumeIntegral() % PIXELFORMAT_MODULO); + size_t power = FDP->ConsumeIntegralInRange(0, 10); + int32_t height = std::pow(2, power); + if (static_cast(height) > size) { + return nullptr; + } + int32_t width = static_cast(size / static_cast(height)); + if (static_cast(width * height) != size) { + return nullptr; + } + opts.size.height = height; + opts.size.width = width; + uint32_t errorCode { 0 }; + return ImageSource::CreateImageSource(pathName, opts, errorCode); +} + +std::unique_ptr ConstructIncrementalImageSource(const uint8_t *data, size_t size) +{ + IncrementalSourceOptions incOpts; + std::string mimeType[] = {"image/jpeg", "image/heic", "image/heif"}; + incOpts.sourceOptions.formatHint = mimeType[FDP->ConsumeIntegral() % SOURCEOPTIONS_MIMETYPE_MODULO]; + incOpts.sourceOptions.pixelFormat = static_cast(FDP->ConsumeIntegral() % PIXELFORMAT_MODULO); + size_t power = FDP->ConsumeIntegralInRange(0, 10); + int32_t height = std::pow(2, power); + if (static_cast(height) > size) { + return nullptr; + } + int32_t width = static_cast(size / static_cast(height)); + if (static_cast(width * height) != size) { + return nullptr; + } + incOpts.sourceOptions.size.height = height; + incOpts.sourceOptions.size.width = width; + uint32_t errorCode { 0 }; + incOpts.incrementalMode = static_cast(FDP->ConsumeIntegral() % INCREMENTAL_MODE_MODULO); + auto incrementalImageSource = ImageSource::CreateIncrementalImageSource(incOpts, errorCode); + if (!incrementalImageSource || errorCode != SUCCESS) { + return nullptr; + } + if (incrementalImageSource->UpdateData(data, size, FDP->ConsumeBool()) != SUCCESS) { + return nullptr; + } + return incrementalImageSource; +} + +void CreateImageSourceFuzzTest() +{ + size_t dataSize = FDP->ConsumeIntegralInRange(0, MAX_SOURCE_SIZE + 1024); + uint8_t *data { nullptr }; + std::vector dataVec; + if (dataSize != 0) { + dataVec = FDP->ConsumeBytes(dataSize); + } + SourceOptions opts; + std::string mimeType[] = {"image/jpeg", "image/heic", "image/heif"}; + opts.formatHint = mimeType[FDP->ConsumeIntegral() % SOURCEOPTIONS_MIMETYPE_MODULO]; + uint32_t errorCode { 0 }; + ImageSource::CreateImageSource(data, dataSize, opts, errorCode); +} + +void CreatePixelMapExFuzzTest(const uint8_t *data, size_t size) +{ + if (data == nullptr) { + return; + } + + auto imageSource = ConstructImageSourceByBuffer(data, size); + if (!imageSource) { + return; + } + + uint32_t index = FDP->ConsumeIntegral(); + uint32_t errorCode { 0 }; + DecodeOptions decodeOpts; + SetFdpDecodeOptions(FDP, decodeOpts); + decodeOpts.desiredSize.width = FDP->ConsumeIntegralInRange(-0xfff, 0xfff); + decodeOpts.desiredSize.height = FDP->ConsumeIntegralInRange(-0xfff, 0xfff); + imageSource->CreatePixelMapEx(index, decodeOpts, errorCode); +} + +void TransformSizeWithDensityFuzzTest(const uint8_t *data, size_t size) +{ + if (data == nullptr) { + return; + } + + auto imageSource = ConstructImageSourceByBuffer(data, size); + if (!imageSource) { + return; + } + + ImageInfo info; + imageSource->GetImageInfo(info); + Size wantSize; + int32_t srcDensity = FDP->ConsumeIntegralInRange(1, 2); + int32_t wantDensity = FDP->ConsumeIntegralInRange(1, 2); + Size dstSize; + imageSource->TransformSizeWithDensity(info.size, srcDensity, wantSize, wantDensity, dstSize); +} + +void IsSupportAllocatorTypeFuzzTest(const uint8_t *data, size_t size) +{ + if (data == nullptr) { + return; + } + + auto imageSource = ConstructImageSourceByBuffer(data, size); + if (!imageSource) { + return; + } + + DecodeOptions decOpts; + decOpts.allocatorType = static_cast(FDP->ConsumeIntegral() % ALLOCATOR_TYPE_MODULO); + decOpts.desiredDynamicRange = + static_cast(FDP->ConsumeIntegral() % DECODE_DYNAMIC_RANGE_MODULO); + int32_t allocatorType = FDP->ConsumeIntegralInRange(1, 4); + imageSource->IsSupportAllocatorType(decOpts, allocatorType); +} + +void SetImageEventHeifParserErrFuzzTest(const uint8_t *data, size_t size) +{ + if (data == nullptr) { + return; + } + + auto imageSource = ConstructImageSourceByBuffer(data, size); + if (!imageSource) { + return; + } + imageSource->heifParseErr_ = FDP->ConsumeIntegral(); + ImageEvent imageEvent; + imageSource->SetImageEventHeifParseErr(imageEvent); +} + +void PromoteDecodingFuzzTest(const uint8_t *data, size_t size) +{ + auto incrementalImageSource = ConstructIncrementalImageSource(data, size); + if (!incrementalImageSource) { + return; + } + if (incrementalImageSource->InitMainDecoder() != SUCCESS) { + return; + } + DecodeOptions decodeOpts; + SetFdpDecodeOptions(FDP, decodeOpts); + uint32_t errorCode { 0 }; + std::unique_ptr incPixelMap = + incrementalImageSource->CreateIncrementalPixelMap(0, decodeOpts, errorCode); + if (!incPixelMap || errorCode != SUCCESS) { + return; + } + uint8_t decodeProgress { 0 }; + incPixelMap->decodingStatus_.state = + static_cast(FDP->ConsumeIntegral() % INCREMENTAL_DECODING_STATE_MODULO); + incPixelMap->PromoteDecoding(decodeProgress); + incPixelMap->DetachFromDecoding(); +} + +void ModifyImagePropertyExFuzzTest(const uint8_t *data, size_t size) +{ + std::vector> imageSources; + imageSources.emplace_back(ConstructImageSourceByBuffer(data, size)); + imageSources.emplace_back(ConstructImageSourceByFd(data, size)); + imageSources.emplace_back(ConstructImageSourceByPath(data, size)); + for (const auto& imageSource : imageSources) { + if (imageSource) { + imageSource->ModifyImagePropertyEx(0, FDP->ConsumeRandomLengthString(), FDP->ConsumeRandomLengthString()); + } + } +} + +void GetImagePropertyFuzzTest(const uint8_t *data, size_t size) +{ + auto imageSource = ConstructImageSourceByBuffer(data, size); + if (!imageSource) { + return; + } + if (imageSource->InitMainDecoder() != SUCCESS) { + return; + } + std::vector IMAGE_KEYS = { "DelayTime", "DisposalType", "GIFLoopCount" }; + for (const auto &key : IMAGE_KEYS) { + int32_t value { 0 }; + imageSource->GetImagePropertyInt(0, key, value); + std::string strValue = ""; + imageSource->GetImagePropertyString(0, key, strValue); + imageSource->GetImagePropertyStringBySync(0, key, strValue); + } +} + +void DecodeSourceInfoFuzzTest(const uint8_t *data, size_t size) +{ + auto imageSource = ConstructImageSourceByBuffer(data, size); + if (!imageSource) { + return; + } + imageSource->decodeState_ = + static_cast(FDP->ConsumeIntegral() % SOURCE_DECODING_STATE_MODULO); + imageSource->DecodeSourceInfo(FDP->ConsumeBool()); +} + +void CreatePictureAtIndexFuzzTest(const uint8_t *data, size_t size) +{ + auto imageSource = ConstructImageSourceByBuffer(data, size); + if (!imageSource) { + return; + } + uint32_t errorCode { 0 }; + imageSource->CreatePictureAtIndex(0, errorCode); +} + +void CreatePictureFuzzTest(const uint8_t *data, size_t size) +{ + auto imageSource = ConstructImageSourceByBuffer(data, size); + if (!imageSource) { + return; + } + DecodingOptionsForPicture opts; + opts.allocatorType = static_cast(FDP->ConsumeIntegral() % ALLOCATOR_TYPE_MODULO); + opts.desiredPixelFormat = static_cast(FDP->ConsumeIntegral() % PIXELFORMAT_MODULO); + for (uint32_t i = 0; i < AUXILIARY_PICTURE_TYPE_MODULO; i++) { + AuxiliaryPictureType tmpType = + static_cast(FDP->ConsumeIntegral() % AUXILIARY_PICTURE_TYPE_MODULO); + opts.desireAuxiliaryPictures.insert(tmpType); + } + uint32_t errorCode { 0 }; + imageSource->CreatePicture(opts, errorCode); +} + +} // namespace Media +} // namespace OHOS + + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider fdp(data, size); + OHOS::Media::FDP = &fdp; + + /* Run your code on data */ + OHOS::Media::CreateImageSourceFuzzTest(); + OHOS::Media::CreatePixelMapExFuzzTest(data, size); + OHOS::Media::TransformSizeWithDensityFuzzTest(data, size); + OHOS::Media::IsSupportAllocatorTypeFuzzTest(data, size); + OHOS::Media::SetImageEventHeifParserErrFuzzTest(data, size); + OHOS::Media::PromoteDecodingFuzzTest(data, size); + OHOS::Media::ModifyImagePropertyExFuzzTest(data, size); + OHOS::Media::GetImagePropertyFuzzTest(data, size); + OHOS::Media::DecodeSourceInfoFuzzTest(data, size); + OHOS::Media::CreatePictureFuzzTest(data, size); + return 0; +}