Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix misc issues due to OSS-fuzz #1173

Merged
merged 6 commits into from
Oct 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 48 additions & 17 deletions src/lib/OpenEXRCore/chunk.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,20 @@ static exr_result_t
extract_chunk_table (
const struct _internal_exr_context* ctxt,
const struct _internal_exr_part* part,
uint64_t** chunktable)
uint64_t** chunktable,
uint64_t* chunkminoffset)
{
uint64_t* ctable = NULL;
uint64_t* ctable = NULL;
uint64_t chunkoff = part->chunk_table_offset;
uint64_t chunkbytes = sizeof (uint64_t) * (uint64_t) part->chunk_count;

*chunkminoffset = chunkoff + chunkbytes;

ctable = (uint64_t*) atomic_load (
EXR_CONST_CAST (atomic_uintptr_t*, &(part->chunk_table)));
if (ctable == NULL)
{
uint64_t chunkoff = part->chunk_table_offset;
uint64_t chunkbytes = sizeof (uint64_t) * (uint64_t) part->chunk_count;
int64_t nread = 0;
int64_t nread = 0;
uintptr_t eptr = 0, nptr = 0;

exr_result_t rv;
Expand Down Expand Up @@ -198,7 +201,7 @@ exr_read_scanline_chunk_info (
int32_t data[3];
int64_t ddata[3];
int64_t fsize;
uint64_t dataoff;
uint64_t chunkmin, dataoff;
cary-ilm marked this conversation as resolved.
Show resolved Hide resolved
exr_attr_box2i_t dw;
uint64_t* ctable;
EXR_PROMOTE_READ_CONST_CONTEXT_AND_PART_OR_ERROR (ctxt, part_index);
Expand Down Expand Up @@ -263,10 +266,23 @@ exr_read_scanline_chunk_info (
cinfo->level_y = 0;

/* need to read from the file to get the packed chunk size */
rv = extract_chunk_table (pctxt, part, &ctable);
rv = extract_chunk_table (pctxt, part, &ctable, &chunkmin);
if (rv != EXR_ERR_SUCCESS) return rv;

fsize = pctxt->file_size;

dataoff = ctable[cidx];
if (dataoff < chunkmin || (fsize > 0 && dataoff > (uint64_t) fsize))
{
return pctxt->print_error (
pctxt,
EXR_ERR_BAD_CHUNK_LEADER,
"Corrupt chunk offset table: scanline %d, chunk index %d recorded at file offset %" PRIu64,
y,
cidx,
dataoff);
}

/* multi part files have the part for validation */
rdcnt = (pctxt->is_multipart) ? 2 : 1;
/* deep has 64-bit data, so be variable about what we read */
Expand Down Expand Up @@ -312,7 +328,6 @@ exr_read_scanline_chunk_info (
miny);
}

fsize = pctxt->file_size;
if (part->storage_mode == EXR_STORAGE_DEEP_SCANLINE)
{
rv = pctxt->do_read (
Expand Down Expand Up @@ -584,8 +599,8 @@ exr_read_tile_chunk_info (
int32_t data[6];
int32_t* tdata;
int32_t cidx, ntoread;
uint64_t dataoff;
int64_t fsize, tend, dend;
uint64_t chunkmin, dataoff;
int64_t nread, fsize, tend, dend;
const exr_attr_chlist_t* chanlist;
const exr_attr_tiledesc_t* tiledesc;
int tilew, tileh;
Expand Down Expand Up @@ -655,14 +670,15 @@ exr_read_tile_chunk_info (
cinfo->level_y = (uint8_t) levely;

chanlist = part->channels->chlist;
texels = (uint64_t) tilew * (uint64_t) tileh;
texels = (uint64_t) tilew * (uint64_t) tileh;
for (int c = 0; c < chanlist->num_channels; ++c)
{
const exr_attr_chlist_entry_t* curc = (chanlist->entries + c);
unpacksize += texels * (uint64_t) ((curc->pixel_type == EXR_PIXEL_HALF) ? 2 : 4);
unpacksize +=
texels * (uint64_t) ((curc->pixel_type == EXR_PIXEL_HALF) ? 2 : 4);
}

rv = extract_chunk_table (pctxt, part, &ctable);
rv = extract_chunk_table (pctxt, part, &ctable, &chunkmin);
if (rv != EXR_ERR_SUCCESS) return rv;

if (part->storage_mode == EXR_STORAGE_DEEP_TILED)
Expand All @@ -677,13 +693,29 @@ exr_read_tile_chunk_info (
else
ntoread = 5;

fsize = pctxt->file_size;

dataoff = ctable[cidx];
rv = pctxt->do_read (
if (dataoff < chunkmin || (fsize > 0 && dataoff > (uint64_t) fsize))
{
return pctxt->print_error (
pctxt,
EXR_ERR_BAD_CHUNK_LEADER,
"Corrupt chunk offset table: tile (%d, %d), level (%d, %d), chunk index %d recorded at file offset %" PRIu64,
tilex,
tiley,
levelx,
levely,
cidx,
dataoff);
}

rv = pctxt->do_read (
pctxt,
data,
(uint64_t) (ntoread) * sizeof (int32_t),
&dataoff,
&fsize,
&nread,
EXR_MUST_READ_ALL);
if (rv != EXR_ERR_SUCCESS)
{
Expand All @@ -698,7 +730,7 @@ exr_read_tile_chunk_info (
levely,
(uint64_t) (ntoread) * sizeof (int32_t),
ctable[cidx],
fsize);
(uint64_t) nread);
}
priv_to_native32 (data, ntoread);

Expand Down Expand Up @@ -778,7 +810,6 @@ exr_read_tile_chunk_info (
levely);
}

fsize = pctxt->file_size;
if (part->storage_mode == EXR_STORAGE_DEEP_TILED)
{
int64_t ddata[3];
Expand Down
9 changes: 9 additions & 0 deletions src/lib/OpenEXRCore/coding.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,15 @@ internal_decode_alloc_buffer (
size_t newsz)
{
void* curbuf = *buf;

/* We might have a zero size here due to y sampling on a scanline
* image where there is an attempt to read that portion of the
* image. Just shortcut here and handle at a higher level where
* there is more context
*/
if (newsz == 0)
return EXR_ERR_SUCCESS;

if (!curbuf || *cursz < newsz)
{
internal_decode_free_buffer (decode, bufid, buf, cursz);
Expand Down
4 changes: 2 additions & 2 deletions src/lib/OpenEXRCore/internal_huf.c
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,7 @@ hufDecode (
const uint8_t* in, // i : compressed input buffer
uint64_t ni, // i : input size (in bits)
uint32_t rlc, // i : run-length code
uint64_t no, // i : expected output size (in bytes)
uint64_t no, // i : expected output size (count of uint16 items)
uint16_t* out)
{
uint64_t c = 0;
Expand Down Expand Up @@ -894,7 +894,7 @@ hufDecode (
return EXR_ERR_CORRUPT_CHUNK;
}

if ((((uintptr_t) out) - ((uintptr_t) outb)) != no)
if (out != oe)
return EXR_ERR_OUT_OF_MEMORY;
return EXR_ERR_SUCCESS;
}
Expand Down
34 changes: 28 additions & 6 deletions src/lib/OpenEXRUtil/ImfCheckFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

#include <vector>
#include <algorithm>
#include <stdlib.h>

OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER

Expand Down Expand Up @@ -1349,10 +1350,10 @@ bool readCoreTiledPart(exr_context_t f, int part, bool reduceMemory, bool reduce
{
exr_coding_channel_info_t & outc = decoder.channels[c];
// fake addr for default rouines
outc.decode_to_ptr = (uint8_t*)0x1000;
outc.decode_to_ptr = (uint8_t*)0x1000 + bytes;
outc.user_pixel_stride = outc.user_bytes_per_element;
outc.user_line_stride = outc.user_pixel_stride * curtw;
bytes += curtw * (uint64_t)outc.user_bytes_per_element * (uint64_t)curth;
bytes += (uint64_t)curtw * (uint64_t)outc.user_bytes_per_element * (uint64_t)curth;
}

doread = true;
Expand Down Expand Up @@ -1390,8 +1391,8 @@ bool readCoreTiledPart(exr_context_t f, int part, bool reduceMemory, bool reduce
exr_coding_channel_info_t & outc = decoder.channels[c];
outc.decode_to_ptr = dptr;
outc.user_pixel_stride = outc.user_bytes_per_element;
outc.user_line_stride = outc.user_pixel_stride * curth;
dptr += curtw * (uint64_t)outc.user_bytes_per_element * (uint64_t)curth;
outc.user_line_stride = outc.user_pixel_stride * curtw;
dptr += (uint64_t)curtw * (uint64_t)outc.user_bytes_per_element * (uint64_t)curth;
}

rv = exr_decoding_run (f, part, &decoder);
Expand Down Expand Up @@ -1453,6 +1454,24 @@ bool checkCoreFile(exr_context_t f, bool reduceMemory, bool reduceTime)

////////////////////////////////////////

static void
core_error_handler_cb (exr_const_context_t f, int code, const char* msg)
{
if (getenv ("EXR_CHECK_ENABLE_PRINTS") != NULL)
{
const char* fn;
if (EXR_ERR_SUCCESS != exr_get_file_name (f, &fn)) fn = "<error>";
fprintf (
stderr,
"ERROR '%s' (%s): %s\n",
fn,
exr_get_error_code_as_string (code),
msg);
}
}

////////////////////////////////////////

bool
runCoreChecks (const char *filename, bool reduceMemory, bool reduceTime)
{
Expand All @@ -1461,6 +1480,8 @@ runCoreChecks (const char *filename, bool reduceMemory, bool reduceTime)
exr_context_t f;
exr_context_initializer_t cinit = EXR_DEFAULT_CONTEXT_INITIALIZER;

cinit.error_handler_fn = &core_error_handler_cb;

rv = exr_start_read (&f, filename, &cinit);
if (rv != EXR_ERR_SUCCESS)
return true;
Expand All @@ -1480,7 +1501,7 @@ struct memdata
size_t bytes;
};

int64_t
static int64_t
memstream_read (
exr_const_context_t f,
void* userdata,
Expand All @@ -1504,7 +1525,7 @@ memstream_read (
return rdsz;
}

int64_t memstream_size (
static int64_t memstream_size (
exr_const_context_t ctxt, void* userdata)
{
if (userdata)
Expand All @@ -1530,6 +1551,7 @@ runCoreChecks (const char *data, size_t numBytes, bool reduceMemory, bool reduce
cinit.user_data = &md;
cinit.read_fn = &memstream_read;
cinit.size_fn = &memstream_size;
cinit.error_handler_fn = &core_error_handler_cb;

rv = exr_start_read (&f, "<memstream>", &cinit);
if (rv != EXR_ERR_SUCCESS)
Expand Down