1 // Copyright 2017 The PDFium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <vector> 6 7 #include "core/fxcodec/gif/cfx_lzwdecompressor.h" 8 #include "third_party/base/numerics/safe_conversions.h" 9 10 // Between 2x and 5x is a standard range for LZW according to a quick 11 // search of papers. Running up to 10x to catch any niche cases. 12 constexpr uint32_t kMinCompressionRatio = 2; 13 constexpr uint32_t kMaxCompressionRatio = 10; 14 15 void LZWFuzz(const uint8_t* src_buf, 16 size_t src_size, 17 uint8_t color_exp, 18 uint8_t code_exp) { 19 std::unique_ptr<CFX_LZWDecompressor> decompressor = 20 CFX_LZWDecompressor::Create(color_exp, code_exp); 21 if (!decompressor) 22 return; 23 24 for (uint32_t compressions_ratio = kMinCompressionRatio; 25 compressions_ratio <= kMaxCompressionRatio; compressions_ratio++) { 26 std::vector<uint8_t> des_buf(compressions_ratio * src_size); 27 // This cast should be safe since the caller is checking for overflow on 28 // the initial data. 29 uint32_t des_size = static_cast<uint32_t>(des_buf.size()); 30 if (CFX_GifDecodeStatus::InsufficientDestSize != 31 decompressor->Decode(const_cast<uint8_t*>(src_buf), src_size, 32 des_buf.data(), &des_size)) 33 return; 34 } 35 } 36 37 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { 38 // Need at least 3 bytes to do anything. 39 if (size < 3) 40 return 0; 41 42 // Normally the GIF would provide the code and color sizes, instead, going 43 // to assume they are the first two bytes of data provided. 44 uint8_t color_exp = data[0]; 45 uint8_t code_exp = data[1]; 46 const uint8_t* lzw_data = data + 2; 47 uint32_t lzw_data_size = static_cast<uint32_t>(size - 2); 48 // Check that there isn't going to be an overflow in the destination buffer 49 // size. 50 if (lzw_data_size > 51 std::numeric_limits<uint32_t>::max() / kMaxCompressionRatio) { 52 return 0; 53 } 54 55 LZWFuzz(lzw_data, lzw_data_size, color_exp, code_exp); 56 57 return 0; 58 } 59