* Copyright (c) 2026 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 "dragdatautil_fuzzer.h"
#include <cstddef>
#include <cstdint>
#include <memory>
#include <fuzzer/FuzzedDataProvider.h>
#include "drag_data.h"
#include "drag_data_util.h"
#include "drag_data_packer.h"
#include "parcel.h"
#include "pixel_map.h"
namespace {
constexpr size_t THRESHOLD = 4;
constexpr int32_t MAX_PIXEL_MAP_WIDTH = 100;
constexpr int32_t MAX_PIXEL_MAP_HEIGHT = 100;
constexpr int32_t MAX_STRING_LENGTH = 50;
constexpr int32_t MAX_SHADOW_NUM = 3;
constexpr int32_t MAX_SUMMARY_ENTRIES = 10;
constexpr uint32_t DEFAULT_PIXEL_COLOR = 0xFF0000FF;
constexpr int32_t MAX_DRAG_NUM = 10;
constexpr int32_t DRAG_NUM_MIN = -10;
constexpr int32_t DRAG_NUM_MAX = 10;
constexpr int32_t MAX_DISPLAY_COORD = 1000;
constexpr size_t MAX_KEY_LENGTH = 20;
constexpr int32_t MAX_VECTOR_SIZE = 5;
constexpr uint32_t MAX_TEST_CASE = 6;
enum class TestCase {
MARSHALLING = 0,
DETAILED_SUMMARYS = 1,
SUMMARY_EXPANDING = 2,
MATERIAL_ID = 3,
MATERIAL_FILTER = 4,
CHECK_DRAG_DATA = 5,
SHADOW_OFFSET = 6,
};
}
namespace OHOS {
namespace Msdp {
namespace DeviceStatus {
std::shared_ptr<Media::PixelMap> CreateFuzzPixelMap(FuzzedDataProvider &provider)
{
int32_t width = provider.ConsumeIntegralInRange<int32_t>(1, MAX_PIXEL_MAP_WIDTH);
int32_t height = provider.ConsumeIntegralInRange<int32_t>(1, MAX_PIXEL_MAP_HEIGHT);
if (width <= 0 || height <= 0) {
return nullptr;
}
Media::InitializationOptions opts;
opts.size.width = width;
opts.size.height = height;
opts.pixelFormat = Media::PixelFormat::BGRA_8888;
opts.alphaType = Media::AlphaType::IMAGE_ALPHA_TYPE_OPAQUE;
int32_t colorLen = width * height;
if (colorLen <= 0 || colorLen > MAX_PIXEL_MAP_WIDTH * MAX_PIXEL_MAP_HEIGHT) {
return nullptr;
}
std::vector<uint32_t> colorPixels(colorLen, DEFAULT_PIXEL_COLOR);
return Media::PixelMap::Create(colorPixels.data(), colorLen, opts);
}
void FuzzDragDataUtilMarshalling(FuzzedDataProvider &provider)
{
DragData dragData;
int32_t shadowNum = provider.ConsumeIntegralInRange<int32_t>(1, MAX_SHADOW_NUM);
for (int32_t i = 0; i < shadowNum; ++i) {
ShadowInfo shadowInfo;
shadowInfo.pixelMap = CreateFuzzPixelMap(provider);
if (shadowInfo.pixelMap) {
shadowInfo.x = provider.ConsumeIntegral<int32_t>();
shadowInfo.y = provider.ConsumeIntegral<int32_t>();
dragData.shadowInfos.push_back(shadowInfo);
}
}
size_t bufferSize = provider.ConsumeIntegralInRange<size_t>(0, MAX_BUFFER_SIZE);
dragData.buffer = provider.ConsumeBytes<uint8_t>(bufferSize);
dragData.udKey = provider.ConsumeBytesAsString(
provider.ConsumeIntegralInRange<size_t>(0, MAX_STRING_LENGTH));
dragData.extraInfo = provider.ConsumeBytesAsString(
provider.ConsumeIntegralInRange<size_t>(0, MAX_STRING_LENGTH));
dragData.filterInfo = provider.ConsumeBytesAsString(
provider.ConsumeIntegralInRange<size_t>(0, MAX_STRING_LENGTH));
dragData.sourceType = provider.ConsumeIntegral<int32_t>();
dragData.dragNum = provider.ConsumeIntegralInRange<int32_t>(1, MAX_DRAG_NUM);
dragData.pointerId = provider.ConsumeIntegral<int32_t>();
dragData.displayX = provider.ConsumeIntegralInRange<int32_t>(0, MAX_DISPLAY_COORD);
dragData.displayY = provider.ConsumeIntegralInRange<int32_t>(0, MAX_DISPLAY_COORD);
dragData.displayId = provider.ConsumeIntegral<int32_t>();
dragData.mainWindow = provider.ConsumeIntegral<int32_t>();
dragData.hasCanceledAnimation = provider.ConsumeBool();
dragData.hasCoordinateCorrected = provider.ConsumeBool();
dragData.isDragDelay = provider.ConsumeBool();
int32_t summaryEntries = provider.ConsumeIntegralInRange<int32_t>(0, MAX_SUMMARY_ENTRIES);
for (int32_t i = 0; i < summaryEntries; ++i) {
std::string key = provider.ConsumeBytesAsString(
provider.ConsumeIntegralInRange<size_t>(1, MAX_KEY_LENGTH));
int64_t value = provider.ConsumeIntegral<int64_t>();
if (!key.empty()) {
dragData.summarys[key] = value;
}
}
Parcel parcel;
bool isCross = provider.ConsumeBool();
DragDataUtil::Marshalling(dragData, parcel, isCross);
DragData dragDataOut;
DragDataUtil::UnMarshalling(parcel, dragDataOut, isCross);
}
void FuzzDragDataUtilDetailedSummarys(FuzzedDataProvider &provider)
{
DragData dragData;
int32_t entries = provider.ConsumeIntegralInRange<int32_t>(0, MAX_SUMMARY_ENTRIES);
for (int32_t i = 0; i < entries; ++i) {
std::string key = provider.ConsumeBytesAsString(
provider.ConsumeIntegralInRange<size_t>(1, MAX_KEY_LENGTH));
int64_t value = provider.ConsumeIntegral<int64_t>();
if (!key.empty()) {
dragData.detailedSummarys[key] = value;
}
}
Parcel parcel;
DragDataUtil::MarshallingDetailedSummarys(dragData, parcel);
DragData dragDataOut;
DragDataUtil::UnMarshallingDetailedSummarys(parcel, dragDataOut);
}
void FuzzDragDataUtilSummaryExpanding(FuzzedDataProvider &provider)
{
DragData dragData;
int32_t formatEntries = provider.ConsumeIntegralInRange<int32_t>(0, MAX_SUMMARY_ENTRIES);
for (int32_t i = 0; i < formatEntries; ++i) {
std::string key = provider.ConsumeBytesAsString(
provider.ConsumeIntegralInRange<size_t>(1, MAX_KEY_LENGTH));
int32_t vecSize = provider.ConsumeIntegralInRange<int32_t>(0, MAX_VECTOR_SIZE);
std::vector<int32_t> values;
for (int32_t j = 0; j < vecSize; ++j) {
values.push_back(provider.ConsumeIntegral<int32_t>());
}
if (!key.empty()) {
dragData.summaryFormat[key] = values;
}
}
dragData.summaryVersion = provider.ConsumeIntegral<int32_t>();
dragData.summaryTotalSize = provider.ConsumeIntegral<int64_t>();
dragData.summaryTag = provider.ConsumeBytesAsString(
provider.ConsumeIntegralInRange<size_t>(0, MAX_STRING_LENGTH));
Parcel parcel;
DragDataUtil::MarshallingSummaryExpanding(dragData, parcel);
DragData dragDataOut;
DragDataUtil::UnMarshallingSummaryExpanding(parcel, dragDataOut);
}
void FuzzDragDataUtilMaterialId(FuzzedDataProvider &provider)
{
DragData dragData;
dragData.materialId = provider.ConsumeIntegral<int32_t>();
Parcel parcel;
DragDataUtil::MarshallingMaterialId(dragData, parcel);
DragData dragDataOut;
DragDataUtil::UnMarshallingMaterialId(parcel, dragDataOut);
}
void FuzzDragDataUtilMaterialFilter(FuzzedDataProvider &provider)
{
DragData dragData;
dragData.isSetMaterialFilter = provider.ConsumeBool();
Parcel parcel;
DragDataUtil::MarshallingMaterialFilter(dragData, parcel);
DragData dragDataOut;
DragDataUtil::UnMarshallingMaterialFilter(parcel, dragDataOut);
}
void FuzzDragDataPackerCheckDragData(FuzzedDataProvider &provider)
{
DragData dragData;
int32_t shadowNum = provider.ConsumeIntegralInRange<int32_t>(0, MAX_SHADOW_NUM);
for (int32_t i = 0; i < shadowNum; ++i) {
ShadowInfo shadowInfo;
shadowInfo.pixelMap = CreateFuzzPixelMap(provider);
if (shadowInfo.pixelMap) {
shadowInfo.x = provider.ConsumeIntegralInRange<int32_t>(
-shadowInfo.pixelMap->GetWidth(), 0);
shadowInfo.y = provider.ConsumeIntegralInRange<int32_t>(
-shadowInfo.pixelMap->GetHeight(), 0);
dragData.shadowInfos.push_back(shadowInfo);
}
}
dragData.dragNum = provider.ConsumeIntegralInRange<int32_t>(DRAG_NUM_MIN, DRAG_NUM_MAX);
size_t bufferSize = provider.ConsumeIntegralInRange<size_t>(0, MAX_BUFFER_SIZE * 2);
dragData.buffer = provider.ConsumeBytes<uint8_t>(bufferSize);
dragData.displayX = provider.ConsumeIntegral<int32_t>();
dragData.displayY = provider.ConsumeIntegral<int32_t>();
DragDataPacker::CheckDragData(dragData);
}
void FuzzShadowOffsetPacker(FuzzedDataProvider &provider)
{
ShadowOffset shadowOffset;
shadowOffset.offsetX = provider.ConsumeIntegral<int32_t>();
shadowOffset.offsetY = provider.ConsumeIntegral<int32_t>();
shadowOffset.width = provider.ConsumeIntegral<int32_t>();
shadowOffset.height = provider.ConsumeIntegral<int32_t>();
Parcel parcel;
ShadowOffsetPacker::Marshalling(shadowOffset, parcel);
ShadowOffset shadowOffsetOut;
ShadowOffsetPacker::UnMarshalling(parcel, shadowOffsetOut);
}
bool DragDataUtilFuzzTest(FuzzedDataProvider &provider)
{
TestCase testCase = static_cast<TestCase>(provider.ConsumeIntegralInRange<uint32_t>(0, MAX_TEST_CASE));
switch (testCase) {
case TestCase::MARSHALLING:
FuzzDragDataUtilMarshalling(provider);
break;
case TestCase::DETAILED_SUMMARYS:
FuzzDragDataUtilDetailedSummarys(provider);
break;
case TestCase::SUMMARY_EXPANDING:
FuzzDragDataUtilSummaryExpanding(provider);
break;
case TestCase::MATERIAL_ID:
FuzzDragDataUtilMaterialId(provider);
break;
case TestCase::MATERIAL_FILTER:
FuzzDragDataUtilMaterialFilter(provider);
break;
case TestCase::CHECK_DRAG_DATA:
FuzzDragDataPackerCheckDragData(provider);
break;
case TestCase::SHADOW_OFFSET:
FuzzShadowOffsetPacker(provider);
break;
default:
break;
}
return true;
}
}
}
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{
if (data == nullptr || size < THRESHOLD) {
return 0;
}
FuzzedDataProvider provider(data, size);
OHOS::Msdp::DeviceStatus::DragDataUtilFuzzTest(provider);
return 0;
}