1/*
2 * Copyright (c) 2023 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
16#include "device_fuzzer.h"
17
18#include <cstddef>
19#include <cstdint>
20#include <securec.h>
21#include <string>
22
23#include "display_common_fuzzer.h"
24
25namespace OHOS {
26using namespace OHOS::HDI::Display::Buffer::V1_0;
27using namespace OHOS::HDI::Display::Composer::V1_2;
28
29static sptr<Composer::V1_2::IDisplayComposerInterface> g_composerInterface = nullptr;
30static std::shared_ptr<IDisplayBuffer> g_bufferInterface = nullptr;
31
32static bool g_isInit = false;
33static const uint8_t* g_data = nullptr;
34static size_t g_dataSize = 0;
35static size_t g_pos;
36
37/*
38* describe: get data from outside untrusted data(g_data) which size is according to sizeof(T)
39* tips: only support basic type
40*/
41template<class T>
42T GetData()
43{
44    T object {};
45    size_t objectSize = sizeof(object);
46    if (g_data == nullptr || objectSize > g_dataSize - g_pos) {
47        return object;
48    }
49    errno_t ret = memcpy_s(&object, objectSize, g_data + g_pos, objectSize);
50    if (ret != EOK) {
51        return {};
52    }
53    g_pos += objectSize;
54    return object;
55}
56
57static int32_t GetAllocInfo(AllocInfo& info)
58{
59    uint32_t lenUsage = GetArrLength(CONVERT_TABLE_USAGE);
60    if (lenUsage == 0) {
61        HDF_LOGE("%{public}s: CONVERT_TABLE_USAGE length is equal to 0", __func__);
62        return DISPLAY_FAILURE;
63    }
64    uint32_t lenFormat = GetArrLength(CONVERT_TABLE_FORMAT);
65    if (lenFormat == 0) {
66        HDF_LOGE("%{public}s: CONVERT_TABLE_FORMAT length is equal to 0", __func__);
67        return DISPLAY_FAILURE;
68    }
69
70    info.width = GetData<uint32_t>() % WIDTH;
71    info.height = GetData<uint32_t>() % HEIGHT;
72    info.usage = CONVERT_TABLE_USAGE[GetData<uint32_t>() % lenUsage];
73    info.format = CONVERT_TABLE_FORMAT[GetData<uint32_t>() % lenFormat];
74    info.expectedSize = info.width * info.height;
75
76    return DISPLAY_SUCCESS;
77}
78
79static int32_t GetIRect(IRect& rect)
80{
81    rect.x = GetData<int32_t>();
82    rect.y = GetData<int32_t>();
83    rect.w = GetData<int32_t>();
84    rect.h = GetData<int32_t>();
85    return DISPLAY_SUCCESS;
86}
87
88BufferHandle* UsingAllocmem()
89{
90    AllocInfo info = { 0 };
91    int32_t ret = GetAllocInfo(info);
92    if (ret != DISPLAY_SUCCESS) {
93        HDF_LOGE("%{public}s: function GetAllocInfo failed", __func__);
94        return nullptr;
95    }
96
97    BufferHandle* handle = nullptr;
98    ret = g_bufferInterface->AllocMem(info, handle);
99    if (ret != DISPLAY_SUCCESS) {
100        HDF_LOGE("%{public}s: function AllocMem failed", __func__);
101        return nullptr;
102    }
103    return handle;
104}
105
106int32_t TestSetClientBufferCacheCount(uint32_t devId)
107{
108    uint32_t cacheCount = GetData<uint32_t>();
109    int32_t ret = g_composerInterface->SetClientBufferCacheCount(devId, cacheCount);
110    if (ret != DISPLAY_SUCCESS) {
111        HDF_LOGE("%{public}s: function SetClientBufferCacheCount failed", __func__);
112        return DISPLAY_FAILURE;
113    }
114    return ret;
115}
116
117int32_t TestGetDisplaySupportedModes(uint32_t devId)
118{
119    DisplayModeInfo info = { 0 };
120    info.width = GetData<int32_t>() % WIDTH;
121    info.height = GetData<int32_t>() % HEIGHT;
122    info.freshRate = GetData<uint32_t>();
123    info.id = GetData<int32_t>();
124
125    std::vector<DisplayModeInfo> infos;
126    infos.push_back(info);
127    int32_t ret = g_composerInterface->GetDisplaySupportedModes(devId, infos);
128    if (ret != DISPLAY_SUCCESS) {
129        HDF_LOGE("%{public}s: function GetDisplaySupportedModes failed", __func__);
130        return DISPLAY_FAILURE;
131    }
132    return ret;
133}
134
135int32_t TestSetGetDisplayMode(uint32_t devId)
136{
137    uint32_t modeId = GetData<uint32_t>();
138    int32_t ret = g_composerInterface->SetDisplayMode(devId, modeId);
139    if (ret != DISPLAY_SUCCESS) {
140        HDF_LOGE("%{public}s: function SetDisplayMode failed", __func__);
141        return DISPLAY_FAILURE;
142    }
143    ret = g_composerInterface->GetDisplayMode(devId, modeId);
144    if (ret != DISPLAY_SUCCESS) {
145        HDF_LOGE("%{public}s: function GetDisplayMode failed", __func__);
146        return DISPLAY_FAILURE;
147    }
148    return ret;
149}
150
151int32_t TestSetGetDisplayPowerStatus(uint32_t devId)
152{
153    uint32_t len = GetArrLength(CONVERT_TABLE_POWER_STATUS);
154    if (len == 0) {
155        HDF_LOGE("%{public}s: CONVERT_TABLE_POWER_STATUS length is equal to 0", __func__);
156        return DISPLAY_FAILURE;
157    }
158    Composer::V1_0::DispPowerStatus status = CONVERT_TABLE_POWER_STATUS[GetData<uint32_t>() % len];
159    int32_t ret = g_composerInterface->SetDisplayPowerStatus(devId, status);
160    if (ret != DISPLAY_SUCCESS) {
161        HDF_LOGE("%{public}s: function SetDisplayPowerStatus failed", __func__);
162        return DISPLAY_FAILURE;
163    }
164    ret = g_composerInterface->GetDisplayPowerStatus(devId, status);
165    if (ret != DISPLAY_SUCCESS) {
166        HDF_LOGE("%{public}s: function GetDisplayPowerStatus failed", __func__);
167        return DISPLAY_FAILURE;
168    }
169    return ret;
170}
171
172int32_t TestPrepareDisplayLayers(uint32_t devId)
173{
174    bool needFlushFb = GetRandBoolValue(GetData<uint32_t>());
175    int32_t ret = g_composerInterface->PrepareDisplayLayers(devId, needFlushFb);
176    if (ret != DISPLAY_SUCCESS) {
177        HDF_LOGE("%{public}s: function PrepareDisplayLayers failed", __func__);
178        return DISPLAY_FAILURE;
179    }
180    return ret;
181}
182
183int32_t TestSetGetDisplayBacklight(uint32_t devId)
184{
185    uint32_t level = GetData<uint32_t>();
186    int32_t ret = g_composerInterface->SetDisplayBacklight(devId, level);
187    if (ret != DISPLAY_SUCCESS) {
188        HDF_LOGE("%{public}s: function SetDisplayBacklight failed", __func__);
189        return DISPLAY_FAILURE;
190    }
191    ret = g_composerInterface->GetDisplayBacklight(devId, level);
192    if (ret != DISPLAY_SUCCESS) {
193        HDF_LOGE("%{public}s: function GetDisplayBacklight failed", __func__);
194        return DISPLAY_FAILURE;
195    }
196    return ret;
197}
198
199int32_t TestGetDisplayProperty(uint32_t devId)
200{
201    uint32_t id = GetData<uint32_t>();
202    uint64_t value = GetData<uint32_t>();
203    int32_t ret = g_composerInterface->GetDisplayProperty(devId, id, value);
204    if (ret != DISPLAY_SUCCESS) {
205        HDF_LOGE("%{public}s: function GetDisplayProperty failed", __func__);
206        return DISPLAY_FAILURE;
207    }
208    return ret;
209}
210
211int32_t TestSetHardwareCursorPosition(uint32_t devId)
212{
213    int32_t x = GetData<uint32_t>();
214    int32_t y = GetData<uint32_t>();
215    int32_t ret = g_composerInterface->SetHardwareCursorPosition(devId, x, y);
216    if ((ret != DISPLAY_SUCCESS) && (ret != DISPLAY_NOT_SUPPORT)) {
217        HDF_LOGE("%{public}s: function SetHardwareCursorPosition failed, %{public}d", __func__, ret);
218        return DISPLAY_FAILURE;
219    }
220    return DISPLAY_SUCCESS;
221}
222
223int32_t TestEnableHardwareCursorStats(uint32_t devId)
224{
225    bool enable = GetRandBoolValue(GetData<uint32_t>());
226    int32_t ret = g_composerInterface->EnableHardwareCursorStats(devId, enable);
227    if ((ret != DISPLAY_SUCCESS) && (ret != DISPLAY_NOT_SUPPORT)) {
228        HDF_LOGE("%{public}s: function EnableHardwareCursorStats failed, %{public}d", __func__, ret);
229        return DISPLAY_FAILURE;
230    }
231    return DISPLAY_SUCCESS;
232}
233
234int32_t TestGetHardwareCursorStats(uint32_t devId)
235{
236    uint32_t frameCount = GetData<uint32_t>();
237    uint32_t vsyncCount = GetData<uint32_t>();
238    int32_t ret = g_composerInterface->GetHardwareCursorStats(devId, frameCount, vsyncCount);
239    if ((ret != DISPLAY_SUCCESS) && (ret != DISPLAY_NOT_SUPPORT)) {
240        HDF_LOGE("%{public}s: function GetHardwareCursorStats failed, %{public}d", __func__, ret);
241        return DISPLAY_FAILURE;
242    }
243    return DISPLAY_SUCCESS;
244}
245
246int32_t TestGetDisplayCompChange(uint32_t devId)
247{
248    std::vector<uint32_t> layers;
249    layers.push_back(GetData<uint32_t>());
250    std::vector<int32_t> types;
251    types.push_back(GetData<int32_t>());
252
253    int32_t ret = g_composerInterface->GetDisplayCompChange(devId, layers, types);
254    if (ret != DISPLAY_SUCCESS) {
255        HDF_LOGE("%{public}s: function GetDisplayCompChange failed", __func__);
256        return DISPLAY_FAILURE;
257    }
258    return ret;
259}
260
261int32_t TestSetDisplayClientCrop(uint32_t devId)
262{
263    IRect rect;
264    int32_t ret = GetIRect(rect);
265    if (ret != DISPLAY_SUCCESS) {
266        HDF_LOGE("%{public}s: function GetIRect failed", __func__);
267        return DISPLAY_FAILURE;
268    }
269    ret = g_composerInterface->SetDisplayClientCrop(devId, rect);
270    if (ret != DISPLAY_SUCCESS) {
271        HDF_LOGE("%{public}s: function SetDisplayClientCrop failed", __func__);
272        return DISPLAY_FAILURE;
273    }
274    return ret;
275}
276
277int32_t TestSetDisplayClientDamage(uint32_t devId)
278{
279    IRect rect;
280    int32_t ret = GetIRect(rect);
281    if (ret != DISPLAY_SUCCESS) {
282        HDF_LOGE("%{public}s: function GetIRect failed", __func__);
283        return DISPLAY_FAILURE;
284    }
285    std::vector<IRect> rects;
286    rects.push_back(rect);
287    ret = g_composerInterface->SetDisplayClientDamage(devId, rects);
288    if (ret != DISPLAY_SUCCESS) {
289        HDF_LOGE("%{public}s: function SetDisplayClientDamage failed", __func__);
290    }
291    return ret;
292}
293
294int32_t TestSetDisplayVsyncEnabled(uint32_t devId)
295{
296    bool enabled = GetRandBoolValue(GetData<uint32_t>());
297    int32_t ret = g_composerInterface->SetDisplayVsyncEnabled(devId, enabled);
298    if (ret != DISPLAY_SUCCESS) {
299        HDF_LOGE("%{public}s: function SetDisplayVsyncEnabled failed", __func__);
300    }
301    return ret;
302}
303
304int32_t TestRegDisplayVBlankCallback(uint32_t devId)
305{
306    uint32_t param1 = GetData<uint32_t>();
307    VBlankCallback param2 = GetData<VBlankCallback>();
308    void* param3 = malloc(PARAM_VOIDPTR_LEN);
309    if (param3 == nullptr) {
310        HDF_LOGE("%{public}s: void* param3 malloc failed", __func__);
311        return DISPLAY_FAILURE;
312    }
313    int32_t ret = g_composerInterface->RegDisplayVBlankCallback(param1, param2, param3);
314    if (ret != DISPLAY_SUCCESS) {
315        HDF_LOGE("%{public}s: function RegDisplayVBlankCallback failed", __func__);
316    }
317    free(param3);
318    param3 = nullptr;
319    return ret;
320}
321
322int32_t TestGetDisplayReleaseFence(uint32_t devId)
323{
324    std::vector<uint32_t> layers;
325    layers.push_back(GetData<uint32_t>());
326    std::vector<int32_t> fences;
327    fences.push_back(GetData<int32_t>());
328
329    int32_t ret = g_composerInterface->GetDisplayReleaseFence(devId, layers, fences);
330    if (ret != DISPLAY_SUCCESS) {
331        HDF_LOGE("%{public}s: function GetDisplayReleaseFence failed", __func__);
332    }
333    return ret;
334}
335
336int32_t TestDestroyVirtualDisplay(uint32_t devId)
337{
338    int32_t ret = g_composerInterface->DestroyVirtualDisplay(devId);
339    if (ret != DISPLAY_SUCCESS) {
340        HDF_LOGE("%{public}s: function DestroyVirtualDisplay failed", __func__);
341    }
342    return ret;
343}
344
345int32_t TestSetVirtualDisplayBuffer(uint32_t devId)
346{
347    int32_t fence = GetData<int32_t>();
348    BufferHandle* buffer = UsingAllocmem();
349    if (buffer == nullptr) {
350        HDF_LOGE("%{public}s: Failed to UsingAllocmem", __func__);
351        return DISPLAY_FAILURE;
352    }
353    int32_t ret = g_composerInterface->SetVirtualDisplayBuffer(devId, *buffer, fence);
354    if (ret != DISPLAY_SUCCESS) {
355        HDF_LOGE("%{public}s: function SetVirtualDisplayBuffer failed", __func__);
356    }
357    g_bufferInterface->FreeMem(*buffer);
358    return ret;
359}
360
361int32_t TestSetDisplayProperty(uint32_t devId)
362{
363    uint32_t id = GetData<uint32_t>();
364    uint64_t value = GetData<uint64_t>();
365    int32_t ret = g_composerInterface->SetDisplayProperty(devId, id, value);
366    if (ret != DISPLAY_SUCCESS) {
367        HDF_LOGE("%{public}s: SetDisplayProperty failed", __func__);
368    }
369    return ret;
370}
371
372int32_t TestCommit(uint32_t devId)
373{
374    int32_t fence = GetData<int32_t>();
375    int32_t ret = g_composerInterface->Commit(devId, fence);
376    if (ret != DISPLAY_SUCCESS) {
377        HDF_LOGE("%{public}s: function Commit failed", __func__);
378    }
379    return ret;
380}
381
382int TestGetDisplaySupportedModesExt(uint32_t devId)
383{
384    std::vector<DisplayModeInfoExt> modes;
385    modes.push_back(GetData<DisplayModeInfoExt>());
386    int32_t ret = g_composerInterface->GetDisplaySupportedModesExt(devId, modes);
387    if ((ret != DISPLAY_SUCCESS) && (ret != DISPLAY_NOT_SUPPORT)) {
388        HDF_LOGE("%{public}s: GetDisplaySupportedModesExt failed", __func__);
389    }
390    return ret;
391}
392
393void TestModeCallback(uint32_t modeId, uint64_t vBlankPeriod, void* data)
394{
395}
396
397int TestSetDisplayModeAsync(uint32_t devId)
398{
399    uint32_t modeid = GetData<uint32_t>();
400    int32_t ret = g_composerInterface->SetDisplayModeAsync(devId, modeid, TestModeCallback);
401    if ((ret != DISPLAY_SUCCESS) && (ret != DISPLAY_NOT_SUPPORT)) {
402        HDF_LOGE("%{public}s: SetDisplayModeAsync failed", __func__);
403    }
404    return ret;
405}
406
407int TestGetDisplayVBlankPeriod(uint32_t devId)
408{
409    uint64_t period = GetData<uint64_t>();
410    int32_t ret = g_composerInterface->GetDisplayVBlankPeriod(devId, period);
411    if ((ret != DISPLAY_SUCCESS) && (ret != DISPLAY_NOT_SUPPORT)) {
412        HDF_LOGE("%{public}s: GetDisplayVBlankPeriod failed", __func__);
413    }
414    return ret;
415}
416
417void TestSeamlessChangeCallback(uint32_t devId, void* data)
418{
419}
420
421int TestRegSeamlessChangeCallback(uint32_t devId)
422{
423    int32_t ret = g_composerInterface->RegSeamlessChangeCallback(TestSeamlessChangeCallback, nullptr);
424    if ((ret != DISPLAY_SUCCESS) && (ret != DISPLAY_NOT_SUPPORT)) {
425        HDF_LOGE("%{public}s: SetDisplayModeAsync failed", __func__);
426    }
427    return ret;
428}
429
430int TestGetSupportedLayerPerFrameParameterKey(uint32_t devId)
431{
432    std::vector<std::string> keys;
433    int32_t ret = g_composerInterface->GetSupportedLayerPerFrameParameterKey(keys);
434    if ((ret != DISPLAY_SUCCESS) && (ret != DISPLAY_NOT_SUPPORT)) {
435        HDF_LOGE("%{public}s: failed with ret=%{public}d", __func__, ret);
436    }
437    return ret;
438}
439
440int TestSetDisplayOverlayResolution(uint32_t devId)
441{
442    uint32_t width = GetData<uint32_t>() % WIDTH;
443    uint32_t height = GetData<uint32_t>() % HEIGHT;
444    int32_t ret = g_composerInterface->SetDisplayOverlayResolution(devId, width, height);
445    if ((ret != DISPLAY_SUCCESS) && (ret != DISPLAY_NOT_SUPPORT)) {
446        HDF_LOGE("%{public}s: failed with ret=%{public}d", __func__, ret);
447    }
448    return ret;
449}
450
451static void TestRefreshCallback(uint32_t devId, void* data)
452{
453}
454
455int TestRegRefreshCallback(uint32_t devId)
456{
457    int32_t ret = g_composerInterface->RegRefreshCallback(TestRefreshCallback, nullptr);
458    if ((ret != DISPLAY_SUCCESS) && (ret != DISPLAY_NOT_SUPPORT)) {
459        HDF_LOGE("%{public}s: failed with ret=%{public}d", __func__, ret);
460    }
461    return ret;
462}
463
464int TestGetDisplaySupportedColorGamuts(uint32_t devId)
465{
466    std::vector<ColorGamut> gamuts;
467    int32_t ret = g_composerInterface->GetDisplaySupportedColorGamuts(devId, gamuts);
468    if ((ret != DISPLAY_SUCCESS) && (ret != DISPLAY_NOT_SUPPORT)) {
469        HDF_LOGE("%{public}s: failed with ret=%{public}d", __func__, ret);
470    }
471    return ret;
472}
473
474int TestGetHDRCapabilityInfos(uint32_t devId)
475{
476    HDRCapability info = { 0 };
477    int32_t ret = g_composerInterface->GetHDRCapabilityInfos(devId, info);
478    if ((ret != DISPLAY_SUCCESS) && (ret != DISPLAY_NOT_SUPPORT)) {
479        HDF_LOGE("%{public}s: failed with ret=%{public}d", __func__, ret);
480    }
481    return ret;
482}
483
484typedef int32_t (*TestFuncs[])(uint32_t);
485
486TestFuncs g_testFuncs = {
487    TestSetClientBufferCacheCount,
488    TestGetDisplaySupportedModes,
489    TestSetGetDisplayMode,
490    TestSetGetDisplayPowerStatus,
491    TestPrepareDisplayLayers,
492    TestSetGetDisplayBacklight,
493    TestGetDisplayProperty,
494    TestSetHardwareCursorPosition,
495    TestEnableHardwareCursorStats,
496    TestGetHardwareCursorStats,
497    TestGetDisplayCompChange,
498    TestSetDisplayClientCrop,
499    TestSetDisplayClientDamage,
500    TestSetDisplayVsyncEnabled,
501    TestGetDisplayReleaseFence,
502    TestDestroyVirtualDisplay,
503    TestSetVirtualDisplayBuffer,
504    TestSetDisplayProperty,
505    TestGetDisplaySupportedModesExt,
506    TestSetDisplayModeAsync,
507    TestGetDisplayVBlankPeriod,
508    TestRegSeamlessChangeCallback,
509    TestGetSupportedLayerPerFrameParameterKey,
510    TestSetDisplayOverlayResolution,
511    TestRegRefreshCallback,
512    TestGetDisplaySupportedColorGamuts,
513    TestGetHDRCapabilityInfos,
514    TestCommit,
515};
516
517bool FuzzTest(const uint8_t* rawData, size_t size)
518{
519    if (rawData == nullptr) {
520        return false;
521    }
522
523    // initialize service
524    if (!g_isInit) {
525        g_isInit = true;
526        g_composerInterface = Composer::V1_2::IDisplayComposerInterface::Get();
527        if (g_composerInterface == nullptr) {
528            HDF_LOGE("%{public}s: get IDisplayComposerInterface failed", __func__);
529            return false;
530        }
531        g_bufferInterface.reset(IDisplayBuffer::Get());
532        if (g_bufferInterface == nullptr) {
533            HDF_LOGE("%{public}s: get IDisplayBuffer failed", __func__);
534            return false;
535        }
536    }
537
538    // initialize data
539    g_data = rawData;
540    g_dataSize = size;
541    g_pos = 0;
542
543    uint32_t code = GetData<uint32_t>();
544    uint32_t devId = GetData<uint32_t>();
545    uint32_t len = GetArrLength(g_testFuncs);
546    if (len == 0) {
547        HDF_LOGE("%{public}s: g_testFuncs length is equal to 0", __func__);
548        return false;
549    }
550
551    int32_t ret = g_testFuncs[code % len](devId);
552    if (ret != DISPLAY_SUCCESS) {
553        HDF_LOGE("function %{public}u failed", code % len);
554        return false;
555    }
556
557    return true;
558}
559} // OHOS
560
561/* Fuzzer entry point */
562extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
563{
564    if (size < OHOS::THRESHOLD) {
565        return 0;
566    }
567
568    OHOS::FuzzTest(data, size);
569    return 0;
570}
571