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