From ab791fc9d69580c1982af726c9f61b533357234f Mon Sep 17 00:00:00 2001 From: Glenn Randers-Pehrson Date: Tue, 10 Oct 2017 20:30:54 -0500 Subject: [PATCH] [libpng16] Add some commonly-used transforms to the libpng fuzzer --- contrib/oss-fuzz/libpng_read_fuzzer.cc | 6 + contrib/oss-fuzz/newcc | 190 ------------------------- 2 files changed, 6 insertions(+), 190 deletions(-) delete mode 100644 contrib/oss-fuzz/newcc diff --git a/contrib/oss-fuzz/libpng_read_fuzzer.cc b/contrib/oss-fuzz/libpng_read_fuzzer.cc index 92c550c04..417c280e0 100644 --- a/contrib/oss-fuzz/libpng_read_fuzzer.cc +++ b/contrib/oss-fuzz/libpng_read_fuzzer.cc @@ -163,6 +163,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { return 0; } + // Set several transforms that browsers typically use: + png_set_gray_to_rgb(png_handler.png_ptr); + png_set_expand(png_handler.png_ptr); + png_set_scale_16(png_handler.png_ptr); + png_set_add_alpha(png_handler.png_ptr, 0xffff, PNG_FILLER_AFTER); + int passes = png_set_interlace_handling(png_handler.png_ptr); png_start_read_image(png_handler.png_ptr); diff --git a/contrib/oss-fuzz/newcc b/contrib/oss-fuzz/newcc deleted file mode 100644 index 0fc9e206c..000000000 --- a/contrib/oss-fuzz/newcc +++ /dev/null @@ -1,190 +0,0 @@ - -// libpng_read_fuzzer.cc -// Copyright 2017 Glenn Randers-Pehrson -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that may -// be found in the LICENSE file https://cs.chromium.org/chromium/src/LICENSE - -// Last changed in libpng 1.6.33beta03 [September 27, 2017] - -// The modifications in 2017 by Glenn Randers-Pehrson include -// 1. addition of a PNG_CLEANUP macro, -// 2. setting the option to ignore ADLER32 checksums, -// 3. adding "#include " which is needed on some platforms -// to provide memcpy(). -// 4. adding read_end_info() and creating an end_info structure. - -#include -#include -#include - -#include - -#define PNG_INTERNAL -#include "png.h" - -struct BufState { - const uint8_t* data; - size_t bytes_left; -}; - -struct PngObjectHandler { - png_infop info_ptr = nullptr; - png_structp png_ptr = nullptr; - png_infop end_info_ptr = nullptr; - png_voidp row_ptr = nullptr; - BufState* buf_state = nullptr; - - ~PngObjectHandler() { - if (row_ptr) - png_free(png_ptr, row_ptr); - if (end_info_ptr) - png_destroy_read_struct(&png_ptr, &info_ptr, &end_info_ptr); - else if (info_ptr) - png_destroy_read_struct(&png_ptr, &info_ptr, nullptr); - else - png_destroy_read_struct(&png_ptr, nullptr, nullptr); - delete buf_state; - } -}; - -void user_read_data(png_structp png_ptr, png_bytep data, png_size_t length) { - BufState* buf_state = static_cast(png_get_io_ptr(png_ptr)); - if (length > buf_state->bytes_left) { - png_error(png_ptr, "read error"); - } - memcpy(data, buf_state->data, length); - buf_state->bytes_left -= length; - buf_state->data += length; -} - -static const int kPngHeaderSize = 8; - -// Entry point for LibFuzzer. -// Roughly follows the libpng book example: -// http://www.libpng.org/pub/png/book/chapter13.html - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - if (size < kPngHeaderSize) { - return 0; - } - - std::vector v(data, data + size); - if (png_sig_cmp(v.data(), 0, kPngHeaderSize)) { - // not a PNG. - return 0; - } - - PngObjectHandler png_handler; - png_handler.png_ptr = nullptr; - png_handler.row_ptr = nullptr; - png_handler.info_ptr = nullptr; - png_handler.end_info_ptr = nullptr; - - png_handler.png_ptr = png_create_read_struct - (PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); - if (!png_handler.png_ptr) { - return 0; - } - -#define PNG_CLEANUP \ - if(png_handler.png_ptr) \ - { \ - if (png_handler.row_ptr) \ - png_free(png_handler.png_ptr, png_handler.row_ptr); \ - if (png_handler.end_info_ptr) \ - png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr,\ - &png_handler.end_info_ptr); \ - else if (png_handler.info_ptr) \ - png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr,\ - nullptr); \ - else \ - png_destroy_read_struct(&png_handler.png_ptr, nullptr, nullptr); \ - png_handler.png_ptr = nullptr; \ - png_handler.row_ptr = nullptr; \ - png_handler.info_ptr = nullptr; \ - png_handler.end_info_ptr = nullptr; \ - } - - png_handler.info_ptr = png_create_info_struct(png_handler.png_ptr); - if (!png_handler.info_ptr) { - PNG_CLEANUP - return 0; - } - - png_handler.end_info_ptr = png_create_info_struct(png_handler.png_ptr); - if (!png_handler.end_info_ptr) { - PNG_CLEANUP - return 0; - } - - /* Treat benign errors as warnings */ - png_set_benign_errors(png_handler.png_ptr, 1); - - png_set_crc_action(png_handler.png_ptr, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE); - -#ifdef PNG_IGNORE_ADLER32 - png_set_option(png_handler.png_ptr, PNG_IGNORE_ADLER32, PNG_OPTION_ON); -#endif - - // Setting up reading from buffer. - png_handler.buf_state = new BufState(); - png_handler.buf_state->data = data + kPngHeaderSize; - png_handler.buf_state->bytes_left = size - kPngHeaderSize; - png_set_read_fn(png_handler.png_ptr, png_handler.buf_state, user_read_data); - png_set_sig_bytes(png_handler.png_ptr, kPngHeaderSize); - - if (setjmp(png_jmpbuf(png_handler.png_ptr))) { - PNG_CLEANUP - return 0; - } - - // Reading. - png_read_info(png_handler.png_ptr, png_handler.info_ptr); - png_read_update_info(png_handler.png_ptr, png_handler.info_ptr); - png_handler.row_ptr = png_malloc( - png_handler.png_ptr, png_get_rowbytes(png_handler.png_ptr, - png_handler.info_ptr)); - - // reset error handler to put png_deleter into scope. - if (setjmp(png_jmpbuf(png_handler.png_ptr))) { - PNG_CLEANUP - return 0; - } - - png_uint_32 width, height; - int bit_depth, color_type, interlace_type, compression_type; - int filter_type; - - if (!png_get_IHDR(png_handler.png_ptr, png_handler.info_ptr, &width, - &height, &bit_depth, &color_type, &interlace_type, - &compression_type, &filter_type)) { - PNG_CLEANUP - return 0; - } - - // This is going to be too slow. - if (width && height > 100000000 / width) { - PNG_CLEANUP - return 0; - } - - int passes = png_set_interlace_handling(png_handler.png_ptr); - png_start_read_image(png_handler.png_ptr); - - /* To do: prevent the optimizer from removing this code entirely */ - for (int pass = 0; pass < passes; ++pass) { - for (png_uint_32 y = 0; y < height; ++y) { - png_read_row(png_handler.png_ptr, - static_cast(png_handler.row_ptr), nullptr); - } - } - - png_read_end(png_handler.png_ptr, png_handler.end_info_ptr); - - PNG_CLEANUP - - /* TO do: exercise the progressive reader here */ - - return 0; -}