diff options
author | Abhishek Arya <inferno@chromium.org> | 2016-11-29 10:58:16 -0800 |
---|---|---|
committer | Abhishek Arya <inferno@chromium.org> | 2016-11-29 10:58:31 -0800 |
commit | c03c92cce0b04ba2be95a8ac421c9d41777e8e7d (patch) | |
tree | a53a87674514234812f01a4c95208cc4554c6c84 /projects/libpng/libpng_read_fuzzer.cc | |
parent | ea87305a11ab9654ea315c666f581785a862dcb6 (diff) | |
parent | ef765503cb3bbf7d2f82cdf01ccc033f6008ac91 (diff) |
Merge branch 'master' of https://github.com/google/oss-fuzz
Diffstat (limited to 'projects/libpng/libpng_read_fuzzer.cc')
-rw-r--r-- | projects/libpng/libpng_read_fuzzer.cc | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/projects/libpng/libpng_read_fuzzer.cc b/projects/libpng/libpng_read_fuzzer.cc new file mode 100644 index 00000000..ca489b09 --- /dev/null +++ b/projects/libpng/libpng_read_fuzzer.cc @@ -0,0 +1,123 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <stddef.h> +#include <stdint.h> + +#include <vector> + +#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_voidp row_ptr = nullptr; + BufState* buf_state = nullptr; + + ~PngObjectHandler() { + if (row_ptr && png_ptr) { + png_free(png_ptr, row_ptr); + } + if (png_ptr && info_ptr) { + png_destroy_read_struct(&png_ptr, &info_ptr, nullptr); + } + delete buf_state; + } +}; + +void user_read_data(png_structp png_ptr, png_bytep data, png_size_t length) { + BufState* buf_state = static_cast<BufState*>(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<unsigned char> v(data, data + size); + if (png_sig_cmp(v.data(), 0, kPngHeaderSize)) { + // not a PNG. + return 0; + } + + PngObjectHandler png_handler; + png_handler.png_ptr = png_create_read_struct + (PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); + if (!png_handler.png_ptr) { + return 0; + } + + png_set_crc_action(png_handler.png_ptr, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE); + + png_handler.info_ptr = png_create_info_struct(png_handler.png_ptr); + if (!png_handler.info_ptr) { + return 0; + } + + // 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); + + // libpng error handling. + if (setjmp(png_jmpbuf(png_handler.png_ptr))) { + return 0; + } + + // Reading. + png_read_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))) { + 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)) { + return 0; + } + + // This is going to be too slow. + if (width && height > 100000000 / width) + return 0; + + int passes = png_set_interlace_handling(png_handler.png_ptr); + png_start_read_image(png_handler.png_ptr); + + 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_bytep>(png_handler.row_ptr), NULL); + } + } + + return 0; +} |