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