From 51c8d748e7be42934e94b9fb6bc074e1af99b145 Mon Sep 17 00:00:00 2001 From: zhaona45 Date: Thu, 4 Sep 2025 10:36:56 +0800 Subject: [PATCH] Add Heif Box Fuzz Test. Signed-off-by: zhaona45 --- .../innerkitsimpl/test/fuzztest/BUILD.gn | 1 + .../fuzztest/imageheifbox_fuzzer/BUILD.gn | 57 +++ .../fuzztest/imageheifbox_fuzzer/corpus/init | 16 + .../include/image_heif_box_fuzzer.h | 19 + .../fuzztest/imageheifbox_fuzzer/project.xml | 25 ++ .../src/image_heif_box_fuzzer.cpp | 419 ++++++++++++++++++ 6 files changed, 537 insertions(+) create mode 100644 frameworks/innerkitsimpl/test/fuzztest/imageheifbox_fuzzer/BUILD.gn create mode 100644 frameworks/innerkitsimpl/test/fuzztest/imageheifbox_fuzzer/corpus/init create mode 100644 frameworks/innerkitsimpl/test/fuzztest/imageheifbox_fuzzer/include/image_heif_box_fuzzer.h create mode 100644 frameworks/innerkitsimpl/test/fuzztest/imageheifbox_fuzzer/project.xml create mode 100644 frameworks/innerkitsimpl/test/fuzztest/imageheifbox_fuzzer/src/image_heif_box_fuzzer.cpp diff --git a/frameworks/innerkitsimpl/test/fuzztest/BUILD.gn b/frameworks/innerkitsimpl/test/fuzztest/BUILD.gn index f6ed4b391..2bed98c6c 100644 --- a/frameworks/innerkitsimpl/test/fuzztest/BUILD.gn +++ b/frameworks/innerkitsimpl/test/fuzztest/BUILD.gn @@ -26,6 +26,7 @@ group("fuzztest") { "imagefwkimagesource2_fuzzer:ImageFwkImageSource2FuzzTest", "imagefwkimagesource3_fuzzer:ImageFwkImageSource3FuzzTest", "imagegifencoder_fuzzer:ImageGifEnCoderFuzzTest", + "imageheifbox_fuzzer:ImageHeifBoxFuzzTest", "imageheifimpl_fuzzer:ImageHeifImplFuzzTest", "imageheifimpl2_fuzzer:ImageHeifImpl2FuzzTest", "imageheifparser_fuzzer:ImageHeifParserFuzzTest", diff --git a/frameworks/innerkitsimpl/test/fuzztest/imageheifbox_fuzzer/BUILD.gn b/frameworks/innerkitsimpl/test/fuzztest/imageheifbox_fuzzer/BUILD.gn new file mode 100644 index 000000000..9ff78c5f1 --- /dev/null +++ b/frameworks/innerkitsimpl/test/fuzztest/imageheifbox_fuzzer/BUILD.gn @@ -0,0 +1,57 @@ +# 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("ImageHeifBoxFuzzTest") { + module_out_path = "image_framework/image_framework" + fuzz_config_file = "$image_subsystem/frameworks/innerkitsimpl/test/fuzztest/imageheifbox_fuzzer" + + include_dirs = [ + "./include", + "$image_subsystem/interfaces/innerkits/include", + "$image_subsystem/plugins/common/libs/image/libextplugin/include", + "$image_subsystem/plugins/common/libs/image/libextplugin/include/heif_impl", + "$image_subsystem/plugins/common/libs/image/libextplugin/include/heif_impl/heif_parser", + "$image_subsystem/frameworks/innerkitsimpl/test/fuzztest/common/include", + ] + + sources = [ "src/image_heif_box_fuzzer.cpp" ] + + defines = [ + "JPEG_HW_DECODE_ENABLE", + "HEIF_HW_DECODE_ENABLE", + ] + + deps = [ + "$image_subsystem/interfaces/innerkits:image_native", + "${image_subsystem}/plugins/common/libs/image/libextplugin:extplugin", + "${image_subsystem}/plugins/common/libs/image/libextplugin:heifimpl", + "${image_subsystem}/plugins/common/libs/image/libextplugin:heifparser", + ] + + external_deps = [ + #"c_utils:utils", + "drivers_interface_codec:libcodec_proxy_4.0", + "drivers_interface_codec:libimage_proxy_2.1", + "graphic_2d:color_manager", + "graphic_surface:surface", + "openmax:libopenmax_static", + ] + + cflags = [ + "-Dprotected=public", + "-Dprivate=public", + ] +} diff --git a/frameworks/innerkitsimpl/test/fuzztest/imageheifbox_fuzzer/corpus/init b/frameworks/innerkitsimpl/test/fuzztest/imageheifbox_fuzzer/corpus/init new file mode 100644 index 000000000..7ade8a0fa --- /dev/null +++ b/frameworks/innerkitsimpl/test/fuzztest/imageheifbox_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 \ No newline at end of file diff --git a/frameworks/innerkitsimpl/test/fuzztest/imageheifbox_fuzzer/include/image_heif_box_fuzzer.h b/frameworks/innerkitsimpl/test/fuzztest/imageheifbox_fuzzer/include/image_heif_box_fuzzer.h new file mode 100644 index 000000000..7b52c993f --- /dev/null +++ b/frameworks/innerkitsimpl/test/fuzztest/imageheifbox_fuzzer/include/image_heif_box_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 FRAMEWORKS_INNERKITSIMPL_TEST_FUZZTEST_IMAGEFRAMEWORK_FUZZER_IMAGEHEIFBOX_FUZZER_H +#define FRAMEWORKS_INNERKITSIMPL_TEST_FUZZTEST_IMAGEFRAMEWORK_FUZZER_IMAGEHEIFBOX_FUZZER_H + +#define FUZZ_PROJECT_NAME "image_heif_box_fuzzer" +#endif \ No newline at end of file diff --git a/frameworks/innerkitsimpl/test/fuzztest/imageheifbox_fuzzer/project.xml b/frameworks/innerkitsimpl/test/fuzztest/imageheifbox_fuzzer/project.xml new file mode 100644 index 000000000..138c61f16 --- /dev/null +++ b/frameworks/innerkitsimpl/test/fuzztest/imageheifbox_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 52428800 + + 300 + + 4096 + + diff --git a/frameworks/innerkitsimpl/test/fuzztest/imageheifbox_fuzzer/src/image_heif_box_fuzzer.cpp b/frameworks/innerkitsimpl/test/fuzztest/imageheifbox_fuzzer/src/image_heif_box_fuzzer.cpp new file mode 100644 index 000000000..a3eec5bc7 --- /dev/null +++ b/frameworks/innerkitsimpl/test/fuzztest/imageheifbox_fuzzer/src/image_heif_box_fuzzer.cpp @@ -0,0 +1,419 @@ +/* + * 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_heif_box_fuzzer.h" + +#include +#include +#include +#include + +#include "box/item_info_box.h" +#include "box/heif_box.h" +#include "box/basic_box.h" +#include "box/item_data_box.h" +#include "box/item_ref_box.h" +#include "box/item_property_box.h" +#include "box/item_property_basic_box.h" +#include "box/item_property_aux_box.h" +#include "box/item_property_color_box.h" +#include "box/item_property_display_box.h" +#include "box/item_property_hvcc_box.h" +#include "box/item_property_transform_box.h" +#include "buffer_source_stream.h" +#include "common_fuzztest_function.h" +#include "ext_stream.h" +#include "HeifDecoder.h" +#include "HeifDecoderImpl.h" +#include "heif_parser.h" +#include "heif_image.h" +#include "heif_stream.h" +#include "include/core/SkStream.h" + +namespace OHOS { +namespace Media { +using namespace OHOS::ImagePlugin; +FuzzedDataProvider* FDP; + +namespace { + static constexpr uint32_t DIRECTION_MODULO = 3; + static constexpr uint32_t NUM_0 = 0; + static constexpr uint32_t NUM_1 = 1; + static constexpr uint32_t NUM_10 = 10; + enum class BOX_TYPE { + IMIR, + IROT, + CLLI, + FTYP, + HDLR, + AUXC, + ISPE, + IREF, + COLR, + MDCV, + PIXI, + RLOC, + IPMA, + IPCO, + }; +} + +std::shared_ptr ConstructIMIRBox() +{ + std::shared_ptr res = std::make_shared(); + if (!res) { + return nullptr; + } + res->direction_ = static_cast(FDP->ConsumeIntegral() % DIRECTION_MODULO); + return res; +} + +std::shared_ptr ConstructIROTBox() +{ + std::shared_ptr res = std::make_shared(); + if (!res) { + return nullptr; + } + res->rotDegree_ = FDP->ConsumeIntegral(); + return res; +} + +std::shared_ptr ConstructCLLIBox() +{ + std::shared_ptr res = std::make_shared(); + if (!res) { + return nullptr; + } + ContentLightLevelInfo levelInfo { + .maxContentLightLevel = FDP->ConsumeIntegral(), + .maxPicAverageLightLevel = FDP->ConsumeIntegral()}; + res->lightLevel_ = levelInfo; + return res; +} + +std::shared_ptr ConstructFTYPBox() +{ + std::shared_ptr res = std::make_shared(); + if (!res) { + return nullptr; + } + res->majorBrand_ = FDP->ConsumeIntegral(); + res->minorVersion_ = FDP->ConsumeIntegral(); + size_t randomSize = FDP->ConsumeIntegralInRange(NUM_1, NUM_10); + for (size_t i = 0; i < randomSize; i++) { + res->compatibleBrands_.emplace_back(FDP->ConsumeIntegral()); + } + return res; +} + +std::shared_ptr ConstructHDLRBox() +{ + std::shared_ptr res = std::make_shared(); + if (!res) { + return nullptr; + } + res->isPreDefined_ = FDP->ConsumeIntegral(); + res->handlerType_ = FDP->ConsumeIntegral(); + for (size_t i = 0; i < HeifHdlrBox::HDLR_BOX_RESERVED_SIZE; i++) { + res->reserved_[i] = FDP->ConsumeIntegral(); + } + res->name_ = FDP->ConsumeRandomLengthString(NUM_10); + return res; +} + +std::shared_ptr ConstructAUXCBox() +{ + std::shared_ptr res = std::make_shared(); + if (!res) { + return nullptr; + } + res->auxType_ = FDP->ConsumeRandomLengthString(NUM_10); + size_t randomSize = FDP->ConsumeIntegralInRange(NUM_1, NUM_10); + res->auxSubtypes_ = FDP->ConsumeBytes(randomSize); + return res; +} + +std::shared_ptr ConstructISPEBox() +{ + std::shared_ptr res = std::make_shared(); + if (!res) { + return nullptr; + } + res->width_ = FDP->ConsumeIntegral(); + res->height_ = FDP->ConsumeIntegral(); + return res; +} + +std::shared_ptr ConstructIREFBox() +{ + std::shared_ptr res = std::make_shared(); + if (!res) { + return nullptr; + } + res->version_ = FDP->ConsumeIntegralInRange(NUM_1, NUM_10); + size_t randomSize = FDP->ConsumeIntegralInRange(NUM_1, NUM_10); + std::vector toItemIds; + for (size_t i = 0; i < randomSize; i++) { + toItemIds.emplace_back(FDP->ConsumeIntegral()); + } + uint32_t fromId = FDP->ConsumeIntegral(); + uint32_t type = FDP->ConsumeIntegral(); + res->AddReferences(fromId, type, toItemIds); + if (!res->HasReferences(fromId)) { + return nullptr; + } + return res; +} + +std::shared_ptr ConstructCOLRBox() +{ + std::shared_ptr res = std::make_shared(); + if (!res) { + return nullptr; + } + if (FDP->ConsumeBool()) { + uint32_t type = FDP->ConsumeIntegral(); + size_t randomSize = FDP->ConsumeIntegralInRange(NUM_1, NUM_10); + std::vector data = FDP->ConsumeBytes(randomSize); + std::shared_ptr profile = std::make_shared(type, data); + if (!profile) { + return nullptr; + } + res->SetColorProfile(profile); + } else { + uint16_t color = FDP->ConsumeIntegral(); + uint16_t transfer = FDP->ConsumeIntegral(); + uint16_t matrix = FDP->ConsumeIntegral(); + uint8_t flag = FDP->ConsumeIntegral(); + std::shared_ptr profile = + std::make_shared(color, transfer, matrix, flag); + if (!profile) { + return nullptr; + } + res->SetColorProfile(profile); + } + return res; +} + +std::shared_ptr ConstructMDCVBox() +{ + std::shared_ptr res = std::make_shared(); + if (!res) { + return nullptr; + } + DisplayColourVolume volume; + volume.red.x = FDP->ConsumeIntegral(); + volume.red.y = FDP->ConsumeIntegral(); + volume.green.x = FDP->ConsumeIntegral(); + volume.green.y = FDP->ConsumeIntegral(); + volume.blue.x = FDP->ConsumeIntegral(); + volume.blue.y = FDP->ConsumeIntegral(); + volume.whitePoint.x = FDP->ConsumeIntegral(); + volume.whitePoint.y = FDP->ConsumeIntegral(); + volume.luminanceMax = FDP->ConsumeIntegralInRange(NUM_1, NUM_10); + volume.luminanceMin = FDP->ConsumeIntegralInRange(NUM_0, volume.luminanceMax); + res->colourVolume_ = volume; + return res; +} + +std::shared_ptr ConstructPIXIBox() +{ + std::shared_ptr res = std::make_shared(); + if (!res) { + return nullptr; + } + size_t randomSize = FDP->ConsumeIntegralInRange(NUM_1, NUM_10); + std::vector data = FDP->ConsumeBytes(randomSize); + res->bitNums_ = data; + return res; +} + +std::shared_ptr ConstructRLOCBox() +{ + std::shared_ptr res = std::make_shared(); + if (!res) { + return nullptr; + } + res->horizontalOffset_ = FDP->ConsumeIntegral(); + res->verticalOffset_ = FDP->ConsumeIntegral(); + return res; +} + +std::shared_ptr ConstructIPMABox() +{ + std::shared_ptr res = std::make_shared(); + if (!res) { + return nullptr; + } + PropertyAssociation property; + property.essential = FDP->ConsumeBool(); + property.propertyIndex = FDP->ConsumeIntegralInRange(NUM_1, NUM_10); + uint32_t itemId = FDP->ConsumeIntegral(); + res->AddProperty(itemId, property); + return res; +} + +std::shared_ptr ConstructIPCOBox() +{ + std::shared_ptr res = std::make_shared(); + if (!res) { + return nullptr; + } + uint32_t type = FDP->ConsumeIntegral(); + size_t randomSize = FDP->ConsumeIntegralInRange(NUM_1, NUM_10); + for (size_t i = 0; i < randomSize; i++) { + std::shared_ptr childBox = std::make_shared(type); + if (!childBox) { + return nullptr; + } + res->AddChild(childBox); + } + return res; +} + +std::shared_ptr ConstructHeifBox(BOX_TYPE type) +{ + switch (type) { + case BOX_TYPE::IMIR: + return ConstructIMIRBox(); + case BOX_TYPE::IROT: + return ConstructIROTBox(); + case BOX_TYPE::CLLI: + return ConstructCLLIBox(); + case BOX_TYPE::FTYP: + return ConstructFTYPBox(); + case BOX_TYPE::HDLR: + return ConstructHDLRBox(); + case BOX_TYPE::AUXC: + return ConstructAUXCBox(); + case BOX_TYPE::ISPE: + return ConstructISPEBox(); + case BOX_TYPE::IREF: + return ConstructIREFBox(); + case BOX_TYPE::COLR: + return ConstructCOLRBox(); + case BOX_TYPE::MDCV: + return ConstructMDCVBox(); + case BOX_TYPE::PIXI: + return ConstructPIXIBox(); + case BOX_TYPE::RLOC: + return ConstructRLOCBox(); + case BOX_TYPE::IPMA: + return ConstructIPMABox(); + case BOX_TYPE::IPCO: + return ConstructIPCOBox(); + default: + break; + } + return nullptr; +} + +std::vector> ConstructWriteHeifBoxes() +{ + std::vector boxTypes { + BOX_TYPE::IMIR, + BOX_TYPE::IROT, + BOX_TYPE::CLLI, + BOX_TYPE::FTYP, + BOX_TYPE::HDLR, + BOX_TYPE::AUXC, + BOX_TYPE::ISPE, + BOX_TYPE::COLR, + BOX_TYPE::MDCV, + BOX_TYPE::PIXI, + BOX_TYPE::RLOC, + BOX_TYPE::IPMA, + BOX_TYPE::IREF + }; + std::vector> res; + for (const auto &type : boxTypes) { + res.emplace_back(ConstructHeifBox(type)); + } + return res; +} + +std::vector> ConstructParseContentBoxes() +{ + std::vector boxTypes { + BOX_TYPE::IMIR, + BOX_TYPE::MDCV + }; + std::vector> res; + for (const auto &type : boxTypes) { + res.emplace_back(ConstructHeifBox(type)); + } + return res; +} + +void HeifBoxWriteFuzzTest() +{ + auto boxes = ConstructWriteHeifBoxes(); + + for (auto box : boxes) { + if (box) { + HeifStreamWriter writer; + box->Write(writer); + } + } +} + +void HeifBoxGetPropertyFuzzTest() +{ + std::shared_ptr ipco = std::static_pointer_cast(ConstructHeifBox(BOX_TYPE::IPCO)); + if (!ipco || ipco->children_.empty()) { + return; + } + std::shared_ptr ipma = std::static_pointer_cast(ConstructHeifBox(BOX_TYPE::IPMA)); + if (!ipma || ipma->entries_.empty()) { + return; + } + uint32_t itemId = ipma->entries_[0].itemId; + uint32_t type = ipco->children_[0]->GetBoxType(); + ipco->GetProperty(itemId, ipma, type); +} + +void HeifBoxParseContentFuzzTest(const uint8_t *data, size_t size) +{ + if (data == nullptr) { + return; + } + auto boxes = ConstructParseContentBoxes(); + for (auto box : boxes) { + if (box) { + std::shared_ptr inputStream = + std::make_shared(data, size, false); + if (!inputStream) { + return; + } + HeifStreamReader reader(inputStream, NUM_0, size); + box->ParseContent(reader); + } + } +} + +} // 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::HeifBoxWriteFuzzTest(); + OHOS::Media::HeifBoxGetPropertyFuzzTest(); + OHOS::Media::HeifBoxParseContentFuzzTest(data, size); + return 0; +} \ No newline at end of file -- Gitee