1 // 2 // Copyright 2016 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // translator_fuzzer.cpp: A libfuzzer fuzzer for the shader translator. 8 9 #include <cstddef> 10 #include <cstdint> 11 #include <iostream> 12 #include <memory> 13 #include <unordered_map> 14 15 #include "angle_gl.h" 16 #include "anglebase/no_destructor.h" 17 #include "compiler/translator/Compiler.h" 18 #include "compiler/translator/util.h" 19 20 using namespace sh; 21 22 struct TranslatorCacheKey 23 { operator ==TranslatorCacheKey24 bool operator==(const TranslatorCacheKey &other) const 25 { 26 return type == other.type && spec == other.spec && output == other.output; 27 } 28 29 uint32_t type = 0; 30 uint32_t spec = 0; 31 uint32_t output = 0; 32 }; 33 34 namespace std 35 { 36 37 template <> 38 struct hash<TranslatorCacheKey> 39 { operator ()std::hash40 std::size_t operator()(const TranslatorCacheKey &k) const 41 { 42 return (hash<uint32_t>()(k.type) << 1) ^ (hash<uint32_t>()(k.spec) >> 1) ^ 43 hash<uint32_t>()(k.output); 44 } 45 }; 46 } // namespace std 47 48 struct TCompilerDeleter 49 { operator ()TCompilerDeleter50 void operator()(TCompiler *compiler) const { DeleteCompiler(compiler); } 51 }; 52 LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)53extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) 54 { 55 // Reserve some size for future compile options 56 const size_t kHeaderSize = 128; 57 58 if (size <= kHeaderSize) 59 { 60 return 0; 61 } 62 63 // Make sure the rest of data will be a valid C string so that we don't have to copy it. 64 if (data[size - 1] != 0) 65 { 66 return 0; 67 } 68 69 uint32_t type = *reinterpret_cast<const uint32_t *>(data); 70 uint32_t spec = *reinterpret_cast<const uint32_t *>(data + 4); 71 uint32_t output = *reinterpret_cast<const uint32_t *>(data + 8); 72 uint64_t options = *reinterpret_cast<const uint64_t *>(data + 12); 73 74 if (type != GL_FRAGMENT_SHADER && type != GL_VERTEX_SHADER) 75 { 76 return 0; 77 } 78 79 if (spec != SH_GLES2_SPEC && type != SH_WEBGL_SPEC && spec != SH_GLES3_SPEC && 80 spec != SH_WEBGL2_SPEC) 81 { 82 return 0; 83 } 84 85 ShShaderOutput shaderOutput = static_cast<ShShaderOutput>(output); 86 if (!(IsOutputGLSL(shaderOutput) || IsOutputESSL(shaderOutput)) && 87 (options & SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER) != 0u) 88 { 89 // This compiler option is only available in ESSL and GLSL. 90 return 0; 91 } 92 93 std::vector<uint32_t> validOutputs; 94 validOutputs.push_back(SH_ESSL_OUTPUT); 95 validOutputs.push_back(SH_GLSL_COMPATIBILITY_OUTPUT); 96 validOutputs.push_back(SH_GLSL_130_OUTPUT); 97 validOutputs.push_back(SH_GLSL_140_OUTPUT); 98 validOutputs.push_back(SH_GLSL_150_CORE_OUTPUT); 99 validOutputs.push_back(SH_GLSL_330_CORE_OUTPUT); 100 validOutputs.push_back(SH_GLSL_400_CORE_OUTPUT); 101 validOutputs.push_back(SH_GLSL_410_CORE_OUTPUT); 102 validOutputs.push_back(SH_GLSL_420_CORE_OUTPUT); 103 validOutputs.push_back(SH_GLSL_430_CORE_OUTPUT); 104 validOutputs.push_back(SH_GLSL_440_CORE_OUTPUT); 105 validOutputs.push_back(SH_GLSL_450_CORE_OUTPUT); 106 validOutputs.push_back(SH_HLSL_3_0_OUTPUT); 107 validOutputs.push_back(SH_HLSL_4_1_OUTPUT); 108 validOutputs.push_back(SH_HLSL_4_0_FL9_3_OUTPUT); 109 bool found = false; 110 for (auto valid : validOutputs) 111 { 112 found = found || (valid == output); 113 } 114 if (!found) 115 { 116 return 0; 117 } 118 119 size -= kHeaderSize; 120 data += kHeaderSize; 121 122 if (!sh::Initialize()) 123 { 124 return 0; 125 } 126 127 TranslatorCacheKey key; 128 key.type = type; 129 key.spec = spec; 130 key.output = output; 131 132 using UniqueTCompiler = std::unique_ptr<TCompiler, TCompilerDeleter>; 133 static angle::base::NoDestructor<std::unordered_map<TranslatorCacheKey, UniqueTCompiler>> 134 translators; 135 136 if (translators->find(key) == translators->end()) 137 { 138 UniqueTCompiler translator( 139 ConstructCompiler(type, static_cast<ShShaderSpec>(spec), shaderOutput)); 140 141 if (translator == nullptr) 142 { 143 return 0; 144 } 145 146 ShBuiltInResources resources; 147 sh::InitBuiltInResources(&resources); 148 149 // Enable all the extensions to have more coverage 150 resources.OES_standard_derivatives = 1; 151 resources.OES_EGL_image_external = 1; 152 resources.OES_EGL_image_external_essl3 = 1; 153 resources.NV_EGL_stream_consumer_external = 1; 154 resources.ARB_texture_rectangle = 1; 155 resources.EXT_blend_func_extended = 1; 156 resources.EXT_draw_buffers = 1; 157 resources.EXT_frag_depth = 1; 158 resources.EXT_shader_texture_lod = 1; 159 resources.WEBGL_debug_shader_precision = 1; 160 resources.EXT_shader_framebuffer_fetch = 1; 161 resources.NV_shader_framebuffer_fetch = 1; 162 resources.ARM_shader_framebuffer_fetch = 1; 163 resources.EXT_YUV_target = 1; 164 resources.APPLE_clip_distance = 1; 165 resources.MaxDualSourceDrawBuffers = 1; 166 resources.EXT_gpu_shader5 = 1; 167 resources.MaxClipDistances = 1; 168 169 if (!translator->Init(resources)) 170 { 171 return 0; 172 } 173 174 (*translators)[key] = std::move(translator); 175 } 176 177 auto &translator = (*translators)[key]; 178 179 const char *shaderStrings[] = {reinterpret_cast<const char *>(data)}; 180 translator->compile(shaderStrings, 1, options); 181 182 return 0; 183 } 184