1 /*
2  * Copyright (c) 2022-2024 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 "rsrendernode_fuzzer.h"
17 
18 #include <cstddef>
19 #include <cstdint>
20 #include <securec.h>
21 
22 #include "pipeline/rs_base_render_node.h"
23 #include "pipeline/rs_canvas_render_node.h"
24 #include "pipeline/rs_context.h"
25 #include "pipeline/rs_dirty_region_manager.h"
26 #include "pipeline/rs_display_render_node.h"
27 #include "pipeline/rs_draw_cmd_list.h"
28 #include "pipeline/rs_occlusion_config.h"
29 #include "pipeline/rs_paint_filter_canvas.h"
30 
31 namespace OHOS {
32 namespace Rosen {
33 
34 namespace {
35 constexpr size_t STR_LEN = 10;
36 const uint8_t* g_data = nullptr;
37 size_t g_size = 0;
38 size_t g_pos;
39 } // namespace
40 
41 /*
42  * describe: get data from outside untrusted data(g_data) which size is according to sizeof(T)
43  * tips: only support basic type
44  */
45 template<class T>
GetData()46 T GetData()
47 {
48     T object {};
49     size_t objectSize = sizeof(object);
50     if (g_data == nullptr || objectSize > g_size - g_pos) {
51         return object;
52     }
53     errno_t ret = memcpy_s(&object, objectSize, g_data + g_pos, objectSize);
54     if (ret != EOK) {
55         return {};
56     }
57     g_pos += objectSize;
58     return object;
59 }
60 
61 /*
62  * get a string from g_data
63  */
GetStringFromData(int strlen)64 std::string GetStringFromData(int strlen)
65 {
66     if (strlen <= 0) {
67         return "fuzz";
68     }
69     char cstr[strlen];
70     cstr[strlen - 1] = '\0';
71     for (int i = 0; i < strlen - 1; i++) {
72         char tmp = GetData<char>();
73         if (tmp == '\0') {
74             tmp = '1';
75         }
76         cstr[i] = tmp;
77     }
78     std::string str(cstr);
79     return str;
80 }
81 
82 struct DrawBuffer {
83     int32_t w;
84     int32_t h;
85 };
86 
87 
RSBaseRenderNodeFuzzTest(const uint8_t * data,size_t size)88 bool RSBaseRenderNodeFuzzTest(const uint8_t* data, size_t size)
89 {
90     if (data == nullptr) {
91         return false;
92     }
93 
94     // initialize
95     g_data = data;
96     g_size = size;
97     g_pos = 0;
98 
99     // get data
100     NodeId id = GetData<NodeId>();
101     std::shared_ptr<RSContext> context = std::make_shared<RSContext>();
102     bool isOnTheTree = GetData<bool>();
103     RSBaseRenderNode::SharedPtr child = std::make_shared<RSCanvasRenderNode>(id, context);
104     int index = GetData<int>();
105     bool skipTransition = GetData<bool>();
106     std::vector<RSBaseRenderNode::SharedPtr> vec = { child };
107     bool isUniRender = GetData<bool>();
108     int64_t timestamp = GetData<int64_t>();
109     bool flag = GetData<bool>();
110     bool recursive = GetData<bool>();
111     bool change = GetData<bool>();
112     int left = GetData<int>();
113     int top = GetData<int>();
114     int width = GetData<int>();
115     int height = GetData<int>();
116     RectI r(left, top, width, height);
117 
118     // test
119     std::shared_ptr<RSRenderNode> node = std::make_shared<RSRenderNode>(id, isOnTheTree, context);
120     node->AddChild(child, index);
121     node->MoveChild(child, index);
122     node->RemoveChild(child, skipTransition);
123     node->RemoveFromTree(skipTransition);
124     node->AddCrossParentChild(child, index);
125     node->CollectSurface(child, vec, isUniRender, false);
126     node->SetIsOnTheTree(flag);
127     node->Animate(timestamp);
128     node->SetIsOnTheTree(flag);
129     node->HasDisappearingTransition(recursive);
130     node->SetTunnelHandleChange(change);
131     node->UpdateChildrenOutOfRectFlag(flag);
132 
133     return true;
134 }
135 
RSCanvasRenderNodeFuzzTest(const uint8_t * data,size_t size)136 bool RSCanvasRenderNodeFuzzTest(const uint8_t* data, size_t size)
137 {
138     if (data == nullptr) {
139         return false;
140     }
141 
142     // initialize
143     g_data = data;
144     g_size = size;
145     g_pos = 0;
146 
147     // getdata
148     NodeId id = GetData<NodeId>();
149     DrawBuffer drawBuffer = GetData<DrawBuffer>();
150     RSModifierType type = GetData<RSModifierType>();
151     std::shared_ptr<Drawing::DrawCmdList> drawCmds = Drawing::DrawCmdList::CreateFromData(
152         { &drawBuffer, sizeof(DrawBuffer) }, true);
153     Drawing::Canvas tmpCanvas;
154     float alpha = GetData<float>();
155     RSPaintFilterCanvas canvas(&tmpCanvas, alpha);
156     RSCanvasRenderNode node(id);
157 
158     // test
159     node.UpdateRecording(drawCmds, type);
160     node.ProcessRenderBeforeChildren(canvas);
161     node.ProcessRenderContents(canvas);
162     node.ProcessRenderAfterChildren(canvas);
163 
164     return true;
165 }
166 
RSContextFuzzTest(const uint8_t * data,size_t size)167 bool RSContextFuzzTest(const uint8_t* data, size_t size)
168 {
169     if (data == nullptr) {
170         return false;
171     }
172 
173     // initialize
174     g_data = data;
175     g_size = size;
176     g_pos = 0;
177 
178     // getdata
179     RSContext rsContext;
180     NodeId id = GetData<NodeId>();
181     std::shared_ptr<RSRenderNode> nodePtr = std::make_shared<RSCanvasRenderNode>(id);
182     rsContext.RegisterAnimatingRenderNode(nodePtr);
183 
184     return true;
185 }
186 
RSDirtyRegionManagerFuzzTest(const uint8_t * data,size_t size)187 bool RSDirtyRegionManagerFuzzTest(const uint8_t* data, size_t size)
188 {
189     if (data == nullptr) {
190         return false;
191     }
192 
193     // initialize
194     g_data = data;
195     g_size = size;
196     g_pos = 0;
197 
198     RSDirtyRegionManager manager;
199     manager.Clear();
200     int left = GetData<int>();
201     int top = GetData<int>();
202     int width = GetData<int>();
203     int height = GetData<int>();
204     RectI rect(left, top, width, height);
205     uint64_t u_id = GetData<uint64_t>();
206     NodeId id = static_cast<NodeId>(u_id);
207     RSRenderNodeType nodeType = GetData<RSRenderNodeType>();
208     DirtyRegionType dirtyType = GetData<DirtyRegionType>();
209     std::map<NodeId, RectI> target;
210     target.insert(std::pair<NodeId, RectI>(id, rect));
211 
212     manager.MergeDirtyRect(rect);
213     manager.IntersectDirtyRect(rect);
214     manager.GetRectFlipWithinSurface(rect);
215     RSDirtyRegionManager::GetPixelAlignedRect(rect, GetData<int32_t>());
216     manager.UpdateDirtyByAligned(GetData<int32_t>());
217     manager.UpdateDirtyRegionInfoForDfx(id, nodeType, dirtyType, rect);
218     manager.GetDirtyRegionInfo(target, nodeType, dirtyType);
219     manager.SetBufferAge(GetData<int>());
220     manager.SetSurfaceSize(GetData<int32_t>(), GetData<int32_t>());
221     manager.IsDebugRegionTypeEnable(GetData<DebugRegionType>());
222 
223     return true;
224 }
225 
RSDisplayRenderNodeFuzzTest(const uint8_t * data,size_t size)226 bool RSDisplayRenderNodeFuzzTest(const uint8_t* data, size_t size)
227 {
228     if (data == nullptr) {
229         return false;
230     }
231 
232     // initialize
233     g_data = data;
234     g_size = size;
235     g_pos = 0;
236 
237     // getdata
238     NodeId id = GetData<NodeId>();
239     uint64_t screenId = GetData<uint64_t>();
240     bool isMirrored = GetData<bool>();
241     NodeId mirrorNodeId = GetData<NodeId>();
242     RSDisplayNodeConfig config = { screenId, isMirrored, mirrorNodeId };
243     int32_t offsetX = GetData<int32_t>();
244     int32_t offsetY = GetData<int32_t>();
245     std::shared_ptr<RSContext> context = std::make_shared<RSContext>();
246     std::shared_ptr<RSBaseRenderNode> node = std::make_shared<RSBaseRenderNode>(id, context);
247     std::vector<RSBaseRenderNode::SharedPtr> vec = { node };
248     bool isUniRender = GetData<bool>();
249     RSDisplayRenderNode::CompositeType type = GetData<RSDisplayRenderNode::CompositeType>();
250     bool flag = GetData<bool>();
251     RSDisplayRenderNode::SharedPtr displayPtrNode = std::make_shared<RSDisplayRenderNode>(id, config, context);
252     bool isMirror = GetData<bool>();
253     bool isSecurityDisplay = GetData<bool>();
254     uint32_t refreshRate = GetData<uint32_t>();
255     uint32_t skipFrameInterval = GetData<uint32_t>();
256     int32_t bufferage = GetData<int32_t>();
257     int left = GetData<int>();
258     int top = GetData<int>();
259     int width = GetData<int>();
260     int height = GetData<int>();
261     RectI rect(left, top, width, height);
262     RSDisplayRenderNode displayNode(id, config, context);
263 
264     displayNode.SetScreenId(screenId);
265     displayNode.SetDisplayOffset(offsetX, offsetY);
266     displayNode.CollectSurface(node, vec, isUniRender, false);
267     displayNode.SetCompositeType(type);
268     displayNode.SetForceSoftComposite(flag);
269     displayNode.SetMirrorSource(displayPtrNode);
270     displayNode.SetIsMirrorDisplay(isMirror);
271     displayNode.SetSecurityDisplay(isSecurityDisplay);
272     displayNode.SkipFrame(refreshRate, skipFrameInterval);
273     displayNode.UpdateDisplayDirtyManager(bufferage);
274     displayNode.UpdateSurfaceNodePos(id, rect);
275 
276     return true;
277 }
278 
RSDrawCmdListFuzzTest(const uint8_t * data,size_t size)279 bool RSDrawCmdListFuzzTest(const uint8_t* data, size_t size)
280 {
281     if (data == nullptr) {
282         return false;
283     }
284 
285     // initialize
286     g_data = data;
287     g_size = size;
288     g_pos = 0;
289 
290     DrawBuffer drawBuffer = GetData<DrawBuffer>();
291     float fLeft = GetData<float>();
292     float fTop = GetData<float>();
293     float fRight = GetData<float>();
294     float fBottom = GetData<float>();
295     Drawing::Canvas drCanvas;
296     Drawing::Rect rect = { fLeft, fTop, fRight, fBottom };
297     float alpha = GetData<float>();
298     RSPaintFilterCanvas canvas(&drCanvas, alpha);
299 
300     // test
301     std::shared_ptr<Drawing::DrawCmdList> list = Drawing::DrawCmdList::CreateFromData(
302         { &drawBuffer, sizeof(DrawBuffer) }, true);
303     list->Playback(drCanvas, &rect);
304     list->Playback(canvas, &rect);
305     return true;
306 }
307 
RSOcclusionConfigFuzzTes(const uint8_t * data,size_t size)308 bool RSOcclusionConfigFuzzTes(const uint8_t* data, size_t size)
309 {
310     if (data == nullptr) {
311         return false;
312     }
313 
314     // initialize
315     g_data = data;
316     g_size = size;
317     g_pos = 0;
318 
319     RSOcclusionConfig config = RSOcclusionConfig::GetInstance();
320     std::string win = GetStringFromData(STR_LEN);
321     config.IsLeashWindow(win);
322     config.IsStartingWindow(win);
323     config.IsAlphaWindow(win);
324     config.IsDividerBar(win);
325 
326     return true;
327 }
328 
329 } // namespace Rosen
330 } // namespace OHOS
331 
332 /* Fuzzer entry point */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)333 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
334 {
335     /* Run your code on data */
336     OHOS::Rosen::RSBaseRenderNodeFuzzTest(data, size);
337     OHOS::Rosen::RSContextFuzzTest(data, size);
338     OHOS::Rosen::RSCanvasRenderNodeFuzzTest(data, size);
339     OHOS::Rosen::RSDirtyRegionManagerFuzzTest(data, size);
340     OHOS::Rosen::RSDisplayRenderNodeFuzzTest(data, size);
341     OHOS::Rosen::RSDrawCmdListFuzzTest(data, size);
342     OHOS::Rosen::RSOcclusionConfigFuzzTes(data, size);
343     return 0;
344 }
345