Loading...
Searching...
No Matches
ojph_expand_fuzz_target.cpp
Go to the documentation of this file.
//***************************************************************************/
// This software is released under the 2-Clause BSD license, included
// below.
//
// Copyright (c) 2019, Aous Naman
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//***************************************************************************/
// This file is part of the OpenJPH software implementation.
// File: ojph_expand_fuzz_target.cpp
// Author: Pierre-Anthony Lemieux
// Date: 17 February 2026
//***************************************************************************/
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <ojph_arch.h>
#include <ojph_file.h>
#include <ojph_params.h>
#include <ojph_mem.h>
#include <ojph_codestream.h>
#include <ojph_message.h>
#include <exception>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
{
// The first 2 bytes are used to control decoder options:
// byte 0 bit 1: force planar mode
// byte 0 bit 2: force interleaved mode
// byte 1: number of resolutions to skip (0-7)
if (Size < 3)
return 0;
uint8_t opts = Data[0];
uint8_t skip_res = Data[1] & 0x07;
Data += 2;
Size -= 2;
bool force_planar = (opts & 0x02) != 0;
bool force_interleaved = (opts & 0x04) != 0;
try
{
ojph::mem_infile infile;
infile.open(reinterpret_cast<const ojph::ui8 *>(Data), Size);
ojph::codestream cs;
// Always enable resilience: all fuzzer inputs are untrusted/mutated,
// so the decoder must use its error-recovery path.
cs.enable_resilience();
cs.read_headers(&infile);
// Guard against inputs that cause excessive decoding work.
{
ojph::param_siz siz = cs.access_siz();
ojph::point extent = siz.get_image_extent();
ojph::point offset = siz.get_image_offset();
ojph::ui64 w = extent.x - offset.x;
ojph::ui64 h = extent.y - offset.y;
if (w * h * siz.get_num_components() > 65536)
{
cs.close();
return 0;
}
ojph::param_cod cod = cs.access_cod();
if (cod.get_num_decompositions() > 5)
{
cs.close();
return 0;
}
// Large precincts cause huge internal buffers and very expensive
// per-row wavelet transforms even for small images.
for (ojph::ui32 lev = 0; lev <= cod.get_num_decompositions(); ++lev)
{
ojph::size psiz = cod.get_precinct_size(lev);
if (psiz.w > 256 || psiz.h > 256)
{
cs.close();
return 0;
}
}
}
if (skip_res > 0)
cs.restrict_input_resolution(skip_res, skip_res);
if (force_planar)
cs.set_planar(true);
else if (force_interleaved)
cs.set_planar(false);
cs.create();
ojph::param_siz siz = cs.access_siz();
// Second guard: cap reconstructed dimensions after create().
{
ojph::ui64 total_recon = 0;
for (ojph::ui32 c = 0; c < siz.get_num_components(); ++c)
total_recon += (ojph::ui64)siz.get_recon_width(c)
* (ojph::ui64)siz.get_recon_height(c);
if (total_recon > 65536)
{
cs.close();
return 0;
}
}
// Time budget: abort if decoding takes too long.
struct timespec start_ts;
clock_gettime(CLOCK_MONOTONIC, &start_ts);
ojph::ui32 pull_count = 0;
const ojph::ui32 MAX_SECONDS = 10;
bool timed_out = false;
if (cs.is_planar())
{
for (ojph::ui32 c = 0; c < siz.get_num_components() && !timed_out; ++c)
{
ojph::ui32 height = siz.get_recon_height(c);
for (ojph::ui32 i = height; i > 0 && !timed_out; --i)
{
ojph::ui32 comp_num;
cs.pull(comp_num);
if (++pull_count % 64 == 0)
{
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
if ((ojph::ui32)(now.tv_sec - start_ts.tv_sec) >= MAX_SECONDS)
timed_out = true;
}
}
}
}
else
{
ojph::ui32 height = siz.get_recon_height(0);
for (ojph::ui32 i = 0; i < height && !timed_out; ++i)
{
for (ojph::ui32 c = 0; c < siz.get_num_components(); ++c)
{
ojph::ui32 comp_num;
cs.pull(comp_num);
if (++pull_count % 64 == 0)
{
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
if ((ojph::ui32)(now.tv_sec - start_ts.tv_sec) >= MAX_SECONDS)
timed_out = true;
}
}
}
}
cs.close();
}
catch (const std::exception &)
{
}
return 0;
}
#ifdef OJPH_FUZZ_TARGET_MAIN
int main(int argc, char **argv) {
if (argc != 2) {
return -1;
}
FILE *f = fopen(argv[1], "rb");
if (!f) { return -1; }
fseek(f, 0, SEEK_END);
long len = ftell(f);
if (len < 0) {
return -1;
}
rewind(f);
// Prepend 2 control bytes (default: no skip)
std::vector<uint8_t> buf(len + 2);
buf[0] = 0;
buf[1] = 0;
size_t n = fread(buf.data() + 2, 1, len, f);
if(n != static_cast<size_t>(len)) {
return -1;
}
fclose(f);
LLVMFuzzerTestOneInput(buf.data(), buf.size());
return 0;
}
#endif
main
int main(int argc, char *argv[])
Definition CMakeCCompilerId.c:907
ojph::codestream
The object represent a codestream.
Definition ojph_codestream.h:89
ojph::codestream::access_siz
param_siz access_siz()
Returns the underlying SIZ marker segment object.
Definition ojph_codestream.cpp:79
ojph::codestream::access_cod
param_cod access_cod()
Returns the underlying COD marker segment object.
Definition ojph_codestream.cpp:85
ojph::codestream::restrict_input_resolution
void restrict_input_resolution(ui32 skipped_res_for_data, ui32 skipped_res_for_recon)
This function restricts resolution decoding for a codestream. It is for a reading (decoding) codestre...
Definition ojph_codestream.cpp:179
ojph::codestream::close
void close()
Call this function to close the underlying file; works for both encoding and decoding codestreams.
Definition ojph_codestream.cpp:206
ojph::codestream::set_planar
void set_planar(bool planar)
Sets the sequence of pushing or pull rows from the machinery.
Definition ojph_codestream.cpp:103
ojph::codestream::enable_resilience
void enable_resilience()
This enables codestream resilience; that is, the library tries its best to decode the codestream,...
Definition ojph_codestream.cpp:167
ojph::codestream::read_headers
void read_headers(infile_base *file)
This call reads the headers of a codestream. It is for a reading (or decoding) codestream,...
Definition ojph_codestream.cpp:173
ojph::codestream::create
void create()
This call is for a decoding (or reading) codestream. Call this function after calling restrict_input_...
Definition ojph_codestream.cpp:187
ojph::codestream::is_planar
bool is_planar() const
Query if the codestream extraction is planar or not. See the documentation for ojph::codestream::set_...
Definition ojph_codestream.cpp:153
ojph::codestream::pull
line_buf * pull(ui32 &comp_num)
This call is to pull one row from the codestream, being decoded. The returned line_buf object holds o...
Definition ojph_codestream.cpp:193
ojph::mem_infile
Definition ojph_file.h:309
ojph::mem_infile::open
void open(const ui8 *data, size_t size)
Definition ojph_file.cpp:337
ojph::param_cod
Definition ojph_params.h:104
ojph::param_cod::get_num_decompositions
ui32 get_num_decompositions() const
Definition ojph_params.cpp:263
ojph::param_cod::get_precinct_size
size get_precinct_size(ui32 level_num) const
Definition ojph_params.cpp:287
ojph::param_siz
Definition ojph_params.h:71
ojph::param_siz::get_image_extent
point get_image_extent() const
Definition ojph_params.cpp:96
ojph::param_siz::get_image_offset
point get_image_offset() const
Definition ojph_params.cpp:102
ojph::param_siz::get_recon_height
ui32 get_recon_height(ui32 comp_num) const
Definition ojph_params.cpp:150
ojph::param_siz::get_recon_width
ui32 get_recon_width(ui32 comp_num) const
Definition ojph_params.cpp:144
ojph::param_siz::get_num_components
ui32 get_num_components() const
Definition ojph_params.cpp:120
ojph::ui64
uint64_t ui64
Definition ojph_defs.h:56
ojph::ui32
uint32_t ui32
Definition ojph_defs.h:54
ojph::ui8
uint8_t ui8
Definition ojph_defs.h:50
ojph_arch.h
ojph_codestream.h
LLVMFuzzerTestOneInput
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
Definition ojph_expand_fuzz_target.cpp:50
ojph_file.h
ojph_mem.h
ojph_message.h
ojph_params.h
ojph::point
Definition ojph_base.h:58
ojph::point::y
ui32 y
Definition ojph_base.h:60
ojph::point::x
ui32 x
Definition ojph_base.h:60
ojph::size
Definition ojph_base.h:48
ojph::size::w
ui32 w
Definition ojph_base.h:50
ojph::size::h
ui32 h
Definition ojph_base.h:51