xref: /aosp_15_r20/external/virglrenderer/tests/fuzzer/virgl_fuzzer.c (revision bbecb9d118dfdb95f99bd754f8fa9be01f189df3)
1*bbecb9d1SAndroid Build Coastguard Worker // Copyright 2018 The Chromium OS Authors. All rights reserved.
2*bbecb9d1SAndroid Build Coastguard Worker //
3*bbecb9d1SAndroid Build Coastguard Worker // Redistribution and use in source and binary forms, with or without
4*bbecb9d1SAndroid Build Coastguard Worker // modification, are permitted provided that the following conditions are
5*bbecb9d1SAndroid Build Coastguard Worker // met:
6*bbecb9d1SAndroid Build Coastguard Worker //
7*bbecb9d1SAndroid Build Coastguard Worker //    * Redistributions of source code must retain the above copyright
8*bbecb9d1SAndroid Build Coastguard Worker // notice, this list of conditions and the following disclaimer.
9*bbecb9d1SAndroid Build Coastguard Worker //    * Redistributions in binary form must reproduce the above
10*bbecb9d1SAndroid Build Coastguard Worker // copyright notice, this list of conditions and the following disclaimer
11*bbecb9d1SAndroid Build Coastguard Worker // in the documentation and/or other materials provided with the
12*bbecb9d1SAndroid Build Coastguard Worker // distribution.
13*bbecb9d1SAndroid Build Coastguard Worker //    * Neither the name of Google Inc. nor the names of its
14*bbecb9d1SAndroid Build Coastguard Worker // contributors may be used to endorse or promote products derived from
15*bbecb9d1SAndroid Build Coastguard Worker // this software without specific prior written permission.
16*bbecb9d1SAndroid Build Coastguard Worker //
17*bbecb9d1SAndroid Build Coastguard Worker // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*bbecb9d1SAndroid Build Coastguard Worker // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*bbecb9d1SAndroid Build Coastguard Worker // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*bbecb9d1SAndroid Build Coastguard Worker // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*bbecb9d1SAndroid Build Coastguard Worker // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*bbecb9d1SAndroid Build Coastguard Worker // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*bbecb9d1SAndroid Build Coastguard Worker // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*bbecb9d1SAndroid Build Coastguard Worker // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*bbecb9d1SAndroid Build Coastguard Worker // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*bbecb9d1SAndroid Build Coastguard Worker // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*bbecb9d1SAndroid Build Coastguard Worker // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*bbecb9d1SAndroid Build Coastguard Worker 
29*bbecb9d1SAndroid Build Coastguard Worker // libfuzzer-based fuzzer for public APIs.
30*bbecb9d1SAndroid Build Coastguard Worker 
31*bbecb9d1SAndroid Build Coastguard Worker #include <assert.h>
32*bbecb9d1SAndroid Build Coastguard Worker #include <stdint.h>
33*bbecb9d1SAndroid Build Coastguard Worker #include <stdlib.h>
34*bbecb9d1SAndroid Build Coastguard Worker #include <string.h>
35*bbecb9d1SAndroid Build Coastguard Worker #include <unistd.h>
36*bbecb9d1SAndroid Build Coastguard Worker 
37*bbecb9d1SAndroid Build Coastguard Worker #include <epoxy/egl.h>
38*bbecb9d1SAndroid Build Coastguard Worker 
39*bbecb9d1SAndroid Build Coastguard Worker #include "util/macros.h"
40*bbecb9d1SAndroid Build Coastguard Worker #include "virglrenderer.h"
41*bbecb9d1SAndroid Build Coastguard Worker 
42*bbecb9d1SAndroid Build Coastguard Worker int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
43*bbecb9d1SAndroid Build Coastguard Worker 
44*bbecb9d1SAndroid Build Coastguard Worker #ifndef CLEANUP_EACH_INPUT
45*bbecb9d1SAndroid Build Coastguard Worker // eglInitialize leaks unless eglTeriminate is called (which only happens
46*bbecb9d1SAndroid Build Coastguard Worker // with CLEANUP_EACH_INPUT), so suppress leak detection on everything
47*bbecb9d1SAndroid Build Coastguard Worker // allocated by it.
48*bbecb9d1SAndroid Build Coastguard Worker const char* __lsan_default_suppressions(void);
__lsan_default_suppressions()49*bbecb9d1SAndroid Build Coastguard Worker const char* __lsan_default_suppressions() {
50*bbecb9d1SAndroid Build Coastguard Worker    return "leak:eglInitialize\n";
51*bbecb9d1SAndroid Build Coastguard Worker }
52*bbecb9d1SAndroid Build Coastguard Worker 
53*bbecb9d1SAndroid Build Coastguard Worker #endif // !CLEANUP_EACH_INPUT
54*bbecb9d1SAndroid Build Coastguard Worker 
55*bbecb9d1SAndroid Build Coastguard Worker struct fuzzer_cookie
56*bbecb9d1SAndroid Build Coastguard Worker {
57*bbecb9d1SAndroid Build Coastguard Worker    EGLDisplay display;
58*bbecb9d1SAndroid Build Coastguard Worker    EGLConfig egl_config;
59*bbecb9d1SAndroid Build Coastguard Worker    EGLContext ctx;
60*bbecb9d1SAndroid Build Coastguard Worker };
61*bbecb9d1SAndroid Build Coastguard Worker 
fuzzer_write_fence(UNUSED void * opaque,UNUSED uint32_t fence)62*bbecb9d1SAndroid Build Coastguard Worker static void fuzzer_write_fence(UNUSED void *opaque, UNUSED uint32_t fence)
63*bbecb9d1SAndroid Build Coastguard Worker {
64*bbecb9d1SAndroid Build Coastguard Worker }
65*bbecb9d1SAndroid Build Coastguard Worker 
fuzzer_create_gl_context(void * cookie,UNUSED int scanout_idx,struct virgl_renderer_gl_ctx_param * param)66*bbecb9d1SAndroid Build Coastguard Worker static virgl_renderer_gl_context fuzzer_create_gl_context(
67*bbecb9d1SAndroid Build Coastguard Worker       void *cookie, UNUSED int scanout_idx,
68*bbecb9d1SAndroid Build Coastguard Worker       struct virgl_renderer_gl_ctx_param *param)
69*bbecb9d1SAndroid Build Coastguard Worker {
70*bbecb9d1SAndroid Build Coastguard Worker    struct fuzzer_cookie *cookie_data = cookie;
71*bbecb9d1SAndroid Build Coastguard Worker    EGLContext shared = param->shared ? eglGetCurrentContext() : NULL;
72*bbecb9d1SAndroid Build Coastguard Worker    const EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 3,
73*bbecb9d1SAndroid Build Coastguard Worker                                       EGL_NONE };
74*bbecb9d1SAndroid Build Coastguard Worker    EGLContext ctx = eglCreateContext(cookie_data->display,
75*bbecb9d1SAndroid Build Coastguard Worker                                      cookie_data->egl_config,
76*bbecb9d1SAndroid Build Coastguard Worker                                      shared,
77*bbecb9d1SAndroid Build Coastguard Worker                                      context_attribs);
78*bbecb9d1SAndroid Build Coastguard Worker    assert(ctx);
79*bbecb9d1SAndroid Build Coastguard Worker 
80*bbecb9d1SAndroid Build Coastguard Worker    return ctx;
81*bbecb9d1SAndroid Build Coastguard Worker }
82*bbecb9d1SAndroid Build Coastguard Worker 
fuzzer_destroy_gl_context(void * cookie,virgl_renderer_gl_context ctx)83*bbecb9d1SAndroid Build Coastguard Worker static void fuzzer_destroy_gl_context(void *cookie,
84*bbecb9d1SAndroid Build Coastguard Worker                                       virgl_renderer_gl_context ctx)
85*bbecb9d1SAndroid Build Coastguard Worker {
86*bbecb9d1SAndroid Build Coastguard Worker    struct fuzzer_cookie *cookie_data = cookie;
87*bbecb9d1SAndroid Build Coastguard Worker    eglDestroyContext(cookie_data->display, ctx);
88*bbecb9d1SAndroid Build Coastguard Worker }
89*bbecb9d1SAndroid Build Coastguard Worker 
fuzzer_make_current(UNUSED void * cookie,UNUSED int scanout_idx,UNUSED virgl_renderer_gl_context ctx)90*bbecb9d1SAndroid Build Coastguard Worker static int fuzzer_make_current(UNUSED void *cookie, UNUSED int scanout_idx,
91*bbecb9d1SAndroid Build Coastguard Worker                                UNUSED virgl_renderer_gl_context ctx)
92*bbecb9d1SAndroid Build Coastguard Worker {
93*bbecb9d1SAndroid Build Coastguard Worker    return 0;
94*bbecb9d1SAndroid Build Coastguard Worker }
95*bbecb9d1SAndroid Build Coastguard Worker 
96*bbecb9d1SAndroid Build Coastguard Worker const int FUZZER_CTX_ID = 1;
97*bbecb9d1SAndroid Build Coastguard Worker const char *SWRAST_ENV = "LIBGL_ALWAYS_SOFTWARE";
98*bbecb9d1SAndroid Build Coastguard Worker 
99*bbecb9d1SAndroid Build Coastguard Worker static struct fuzzer_cookie cookie;
100*bbecb9d1SAndroid Build Coastguard Worker 
101*bbecb9d1SAndroid Build Coastguard Worker static struct virgl_renderer_callbacks fuzzer_cbs = {
102*bbecb9d1SAndroid Build Coastguard Worker    .version = 1,
103*bbecb9d1SAndroid Build Coastguard Worker    .write_fence = fuzzer_write_fence,
104*bbecb9d1SAndroid Build Coastguard Worker    .create_gl_context = fuzzer_create_gl_context,
105*bbecb9d1SAndroid Build Coastguard Worker    .destroy_gl_context = fuzzer_destroy_gl_context,
106*bbecb9d1SAndroid Build Coastguard Worker    .make_current = fuzzer_make_current,
107*bbecb9d1SAndroid Build Coastguard Worker };
108*bbecb9d1SAndroid Build Coastguard Worker 
109*bbecb9d1SAndroid Build Coastguard Worker static bool initialized = false;
110*bbecb9d1SAndroid Build Coastguard Worker 
initialize_environment()111*bbecb9d1SAndroid Build Coastguard Worker static int initialize_environment()
112*bbecb9d1SAndroid Build Coastguard Worker {
113*bbecb9d1SAndroid Build Coastguard Worker    if (!initialized) {
114*bbecb9d1SAndroid Build Coastguard Worker       EGLBoolean ok;
115*bbecb9d1SAndroid Build Coastguard Worker 
116*bbecb9d1SAndroid Build Coastguard Worker       // Force SW rendering unless env variable is already set.
117*bbecb9d1SAndroid Build Coastguard Worker       setenv(SWRAST_ENV, "true", 0);
118*bbecb9d1SAndroid Build Coastguard Worker 
119*bbecb9d1SAndroid Build Coastguard Worker       cookie.display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
120*bbecb9d1SAndroid Build Coastguard Worker       assert(cookie.display != EGL_NO_DISPLAY);
121*bbecb9d1SAndroid Build Coastguard Worker 
122*bbecb9d1SAndroid Build Coastguard Worker       ok = eglInitialize(cookie.display, NULL, NULL);
123*bbecb9d1SAndroid Build Coastguard Worker       assert(ok);
124*bbecb9d1SAndroid Build Coastguard Worker 
125*bbecb9d1SAndroid Build Coastguard Worker       const EGLint config_attribs[] = { EGL_SURFACE_TYPE, EGL_DONT_CARE,
126*bbecb9d1SAndroid Build Coastguard Worker                                         EGL_NONE };
127*bbecb9d1SAndroid Build Coastguard Worker       EGLint num_configs;
128*bbecb9d1SAndroid Build Coastguard Worker       ok = eglChooseConfig(cookie.display, config_attribs,
129*bbecb9d1SAndroid Build Coastguard Worker                            &cookie.egl_config, 1, &num_configs);
130*bbecb9d1SAndroid Build Coastguard Worker       assert(ok);
131*bbecb9d1SAndroid Build Coastguard Worker 
132*bbecb9d1SAndroid Build Coastguard Worker       ok = eglBindAPI(EGL_OPENGL_ES_API);
133*bbecb9d1SAndroid Build Coastguard Worker       assert(ok);
134*bbecb9d1SAndroid Build Coastguard Worker 
135*bbecb9d1SAndroid Build Coastguard Worker       const EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 3,
136*bbecb9d1SAndroid Build Coastguard Worker                                          EGL_NONE };
137*bbecb9d1SAndroid Build Coastguard Worker       cookie.ctx = eglCreateContext(cookie.display, cookie.egl_config,
138*bbecb9d1SAndroid Build Coastguard Worker                                     EGL_NO_CONTEXT, context_attribs);
139*bbecb9d1SAndroid Build Coastguard Worker       assert(cookie.ctx != EGL_NO_CONTEXT);
140*bbecb9d1SAndroid Build Coastguard Worker 
141*bbecb9d1SAndroid Build Coastguard Worker       ok = eglMakeCurrent(cookie.display, EGL_NO_SURFACE, EGL_NO_SURFACE,
142*bbecb9d1SAndroid Build Coastguard Worker                           cookie.ctx);
143*bbecb9d1SAndroid Build Coastguard Worker       assert(ok);
144*bbecb9d1SAndroid Build Coastguard Worker 
145*bbecb9d1SAndroid Build Coastguard Worker       initialized = true;
146*bbecb9d1SAndroid Build Coastguard Worker    }
147*bbecb9d1SAndroid Build Coastguard Worker 
148*bbecb9d1SAndroid Build Coastguard Worker    return FUZZER_CTX_ID;
149*bbecb9d1SAndroid Build Coastguard Worker }
150*bbecb9d1SAndroid Build Coastguard Worker 
151*bbecb9d1SAndroid Build Coastguard Worker #ifdef CLEANUP_EACH_INPUT
cleanup_environment()152*bbecb9d1SAndroid Build Coastguard Worker static void cleanup_environment()
153*bbecb9d1SAndroid Build Coastguard Worker {
154*bbecb9d1SAndroid Build Coastguard Worker    if (cookie.ctx != EGL_NO_CONTEXT) {
155*bbecb9d1SAndroid Build Coastguard Worker       eglMakeCurrent(cookie.display, NULL, NULL, NULL);
156*bbecb9d1SAndroid Build Coastguard Worker       eglDestroyContext(cookie.display, cookie.ctx);
157*bbecb9d1SAndroid Build Coastguard Worker    }
158*bbecb9d1SAndroid Build Coastguard Worker 
159*bbecb9d1SAndroid Build Coastguard Worker    if (cookie.display != EGL_NO_DISPLAY) {
160*bbecb9d1SAndroid Build Coastguard Worker       eglTerminate(cookie.display);
161*bbecb9d1SAndroid Build Coastguard Worker    }
162*bbecb9d1SAndroid Build Coastguard Worker 
163*bbecb9d1SAndroid Build Coastguard Worker    initialized = false;
164*bbecb9d1SAndroid Build Coastguard Worker }
165*bbecb9d1SAndroid Build Coastguard Worker #endif
166*bbecb9d1SAndroid Build Coastguard Worker 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)167*bbecb9d1SAndroid Build Coastguard Worker int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
168*bbecb9d1SAndroid Build Coastguard Worker {
169*bbecb9d1SAndroid Build Coastguard Worker    uint32_t ctx_id = initialize_environment();
170*bbecb9d1SAndroid Build Coastguard Worker    int ret;
171*bbecb9d1SAndroid Build Coastguard Worker 
172*bbecb9d1SAndroid Build Coastguard Worker    // There are trade-offs here between ensuring that state is not persisted
173*bbecb9d1SAndroid Build Coastguard Worker    // between invocations of virgl_renderer_submit_cmd, and to avoid leaking
174*bbecb9d1SAndroid Build Coastguard Worker    // resources that comes with repeated dlopen()/dlclose()ing the mesa
175*bbecb9d1SAndroid Build Coastguard Worker    // driver with each eglInitialize()/eglTerminate() if CLEANUP_EACH_INPUT
176*bbecb9d1SAndroid Build Coastguard Worker    // is set.
177*bbecb9d1SAndroid Build Coastguard Worker 
178*bbecb9d1SAndroid Build Coastguard Worker    ret = virgl_renderer_init(&cookie, 0, &fuzzer_cbs);
179*bbecb9d1SAndroid Build Coastguard Worker    assert(!ret);
180*bbecb9d1SAndroid Build Coastguard Worker 
181*bbecb9d1SAndroid Build Coastguard Worker    const char *name = "fuzzctx";
182*bbecb9d1SAndroid Build Coastguard Worker    ret = virgl_renderer_context_create(ctx_id, strlen(name), name);
183*bbecb9d1SAndroid Build Coastguard Worker    assert(!ret);
184*bbecb9d1SAndroid Build Coastguard Worker 
185*bbecb9d1SAndroid Build Coastguard Worker    virgl_renderer_submit_cmd((void *) data, ctx_id, size / sizeof(uint32_t));
186*bbecb9d1SAndroid Build Coastguard Worker 
187*bbecb9d1SAndroid Build Coastguard Worker    virgl_renderer_context_destroy(ctx_id);
188*bbecb9d1SAndroid Build Coastguard Worker 
189*bbecb9d1SAndroid Build Coastguard Worker    virgl_renderer_cleanup(&cookie);
190*bbecb9d1SAndroid Build Coastguard Worker 
191*bbecb9d1SAndroid Build Coastguard Worker #ifdef CLEANUP_EACH_INPUT
192*bbecb9d1SAndroid Build Coastguard Worker    // The following cleans up between each input which is a lot slower.
193*bbecb9d1SAndroid Build Coastguard Worker    cleanup_environment();
194*bbecb9d1SAndroid Build Coastguard Worker #endif
195*bbecb9d1SAndroid Build Coastguard Worker 
196*bbecb9d1SAndroid Build Coastguard Worker    return 0;
197*bbecb9d1SAndroid Build Coastguard Worker }
198