tinyexr: Update to pristine commit e385dad (security update)

This commit is contained in:
Rémi Verschelde 2018-01-13 13:46:03 +01:00
parent 00abb1f201
commit 76e5b048d0
2 changed files with 179 additions and 84 deletions

View File

@ -431,7 +431,7 @@ comments and a patch is provided in the squish/ folder.
## tinyexr
- Upstream: https://github.com/syoyo/tinyexr
- Version: 0.9.5+ (git 9f784ca - 24 October 2017)
- Version: git (e385dad, 2018)
- License: BSD-3-Clause
Files extracted from upstream source:

View File

@ -410,8 +410,8 @@ extern int LoadDeepEXR(DeepImage *out_image, const char *filename,
// Returns negative value and may set error string in `err` when there's an
// error
extern int LoadEXRFromMemory(float **out_rgba, int *width, int *height,
const unsigned char *memory, size_t size,
const char **err);
const unsigned char *memory, size_t size,
const char **err);
#ifdef __cplusplus
}
@ -444,7 +444,8 @@ extern int LoadEXRFromMemory(float **out_rgba, int *width, int *height,
#if TINYEXR_USE_MINIZ
#else
// Issue #46. Please include your own zlib-compatible API header before including `tinyexr.h`
// Issue #46. Please include your own zlib-compatible API header before
// including `tinyexr.h`
//#include "zlib.h"
#endif
@ -488,6 +489,12 @@ namespace miniz {
#if __has_warning("-Wcomma")
#pragma clang diagnostic ignored "-Wcomma"
#endif
#if __has_warning("-Wmacro-redefined")
#pragma clang diagnostic ignored "-Wmacro-redefined"
#endif
#if __has_warning("-Wcast-qual")
#pragma clang diagnostic ignored "-Wcast-qual"
#endif
#endif
/* miniz.c v1.15 - public domain deflate/inflate, zlib-subset, ZIP
@ -6887,8 +6894,6 @@ void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename,
#ifdef _MSC_VER
#pragma warning(pop)
#endif
}
#else
@ -7079,11 +7084,18 @@ static FP16 float_to_half_full(FP32 f) {
// #define IMF_B44_COMPRESSION 6
// #define IMF_B44A_COMPRESSION 7
static const char *ReadString(std::string *s, const char *ptr) {
static const char *ReadString(std::string *s, const char *ptr, size_t len) {
// Read untile NULL(\0).
const char *p = ptr;
const char *q = ptr;
while ((*q) != 0) q++;
while ((size_t(q - ptr) < len) && (*q) != 0) {
q++;
}
if (size_t(q - ptr) >= len) {
(*s) = std::string();
return NULL;
}
(*s) = std::string(p, q);
@ -7120,6 +7132,10 @@ static bool ReadAttribute(std::string *name, std::string *type,
memcpy(&data_len, marker, sizeof(uint32_t));
tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len));
if (data_len == 0) {
return false;
}
marker += sizeof(uint32_t);
size -= sizeof(uint32_t);
@ -7210,7 +7226,7 @@ typedef struct {
}
} HeaderInfo;
static void ReadChannelInfo(std::vector<ChannelInfo> &channels,
static bool ReadChannelInfo(std::vector<ChannelInfo> &channels,
const std::vector<unsigned char> &data) {
const char *p = reinterpret_cast<const char *>(&data.at(0));
@ -7219,7 +7235,18 @@ static void ReadChannelInfo(std::vector<ChannelInfo> &channels,
break;
}
ChannelInfo info;
p = ReadString(&info.name, p);
tinyexr_int64 data_len = static_cast<tinyexr_int64>(data.size()) - (p - reinterpret_cast<const char *>(data.data()));
if (data_len < 0) {
return false;
}
p = ReadString(
&info.name, p, size_t(data_len));
if ((p == NULL) && (info.name.empty())) {
// Buffer overrun. Issue #51.
return false;
}
memcpy(&info.pixel_type, p, sizeof(int));
p += 4;
@ -7236,6 +7263,8 @@ static void ReadChannelInfo(std::vector<ChannelInfo> &channels,
channels.push_back(info);
}
return true;
}
static void WriteChannelInfo(std::vector<unsigned char> &data,
@ -7361,25 +7390,27 @@ static void CompressZip(unsigned char *dst,
}
}
static void DecompressZip(unsigned char *dst,
static bool DecompressZip(unsigned char *dst,
unsigned long *uncompressed_size /* inout */,
const unsigned char *src, unsigned long src_size) {
if ((*uncompressed_size) == src_size) {
// Data is not compressed(Issue 40).
memcpy(dst, src, src_size);
return;
return true;
}
std::vector<unsigned char> tmpBuf(*uncompressed_size);
#if TINYEXR_USE_MINIZ
int ret =
miniz::mz_uncompress(&tmpBuf.at(0), uncompressed_size, src, src_size);
assert(ret == miniz::MZ_OK);
(void)ret;
if (miniz::MZ_OK != ret) {
return false;
}
#else
int ret = uncompress(&tmpBuf.at(0), uncompressed_size, src, src_size);
assert(ret == Z_OK);
(void)ret;
if (Z_OK != ret) {
return false;
}
#endif
//
@ -7419,6 +7450,8 @@ static void DecompressZip(unsigned char *dst,
break;
}
}
return true;
}
// RLE code from OpenEXR --------------------------------------
@ -7443,7 +7476,6 @@ static void DecompressZip(unsigned char *dst,
// conformant name: _strdup.
#endif
const int MIN_RUN_LENGTH = 3;
const int MAX_RUN_LENGTH = 127;
@ -7673,6 +7705,11 @@ static void DecompressRle(unsigned char *dst,
#pragma clang diagnostic ignored "-Wsign-conversion"
#pragma clang diagnostic ignored "-Wc++11-extensions"
#pragma clang diagnostic ignored "-Wconversion"
#if __has_warning("-Wcast-qual")
#pragma clang diagnostic ignored "-Wcast-qual"
#endif
#endif
//
@ -8934,7 +8971,6 @@ static void applyLut(const unsigned short lut[USHORT_RANGE],
#pragma warning(pop)
#endif
static bool CompressPiz(unsigned char *outPtr, unsigned int *outSize,
const unsigned char *inPtr, size_t inSize,
const std::vector<ChannelInfo> &channelInfo,
@ -9373,7 +9409,7 @@ bool CompressZfp(std::vector<unsigned char> *outBuf, unsigned int *outSize,
// -----------------------------------------------------------------
//
static void DecodePixelData(/* out */ unsigned char **out_images,
static bool DecodePixelData(/* out */ unsigned char **out_images,
const int *requested_pixel_types,
const unsigned char *data_ptr, size_t data_len,
int compression_type, int line_order, int width,
@ -9509,6 +9545,7 @@ static void DecodePixelData(/* out */ unsigned char **out_images,
}
#else
assert(0 && "PIZ is enabled in this build");
return false;
#endif
} else if (compression_type == TINYEXR_COMPRESSIONTYPE_ZIPS ||
@ -9520,9 +9557,11 @@ static void DecodePixelData(/* out */ unsigned char **out_images,
unsigned long dstLen = static_cast<unsigned long>(outBuf.size());
assert(dstLen > 0);
tinyexr::DecompressZip(reinterpret_cast<unsigned char *>(&outBuf.at(0)),
if (!tinyexr::DecompressZip(reinterpret_cast<unsigned char *>(&outBuf.at(0)),
&dstLen, data_ptr,
static_cast<unsigned long>(data_len));
static_cast<unsigned long>(data_len))) {
return false;
}
// For ZIP_COMPRESSION:
// pixel sample data for channel 0 for scanline 0
@ -9633,6 +9672,7 @@ static void DecodePixelData(/* out */ unsigned char **out_images,
}
} else {
assert(0);
return false;
}
}
} else if (compression_type == TINYEXR_COMPRESSIONTYPE_RLE) {
@ -9756,6 +9796,7 @@ static void DecodePixelData(/* out */ unsigned char **out_images,
}
} else {
assert(0);
return false;
}
}
} else if (compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) {
@ -9764,7 +9805,7 @@ static void DecodePixelData(/* out */ unsigned char **out_images,
if (!FindZFPCompressionParam(&zfp_compression_param, attributes,
num_attributes)) {
assert(0);
return;
return false;
}
// Allocate original data size.
@ -9818,6 +9859,7 @@ static void DecodePixelData(/* out */ unsigned char **out_images,
}
} else {
assert(0);
return false;
}
}
#else
@ -9825,6 +9867,7 @@ static void DecodePixelData(/* out */ unsigned char **out_images,
(void)num_attributes;
(void)num_channels;
assert(0);
return false;
#endif
} else if (compression_type == TINYEXR_COMPRESSIONTYPE_NONE) {
for (size_t c = 0; c < num_channels; c++) {
@ -9873,6 +9916,7 @@ static void DecodePixelData(/* out */ unsigned char **out_images,
}
} else {
assert(0);
return false;
}
} else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) {
const float *line_ptr = reinterpret_cast<const float *>(
@ -9913,6 +9957,8 @@ static void DecodePixelData(/* out */ unsigned char **out_images,
}
}
}
return true;
}
static void DecodeTiledPixelData(
@ -10161,7 +10207,12 @@ static int ParseEXRHeader(HeaderInfo *info, bool *empty_header,
// xSampling: int
// ySampling: int
ReadChannelInfo(info->channels, data);
if (!ReadChannelInfo(info->channels, data)) {
if (err) {
(*err) = "Failed to parse channel info.";
}
return TINYEXR_ERROR_INVALID_DATA;
}
if (info->channels.size() < 1) {
if (err) {
@ -10173,16 +10224,19 @@ static int ParseEXRHeader(HeaderInfo *info, bool *empty_header,
has_channels = true;
} else if (attr_name.compare("dataWindow") == 0) {
memcpy(&info->data_window[0], &data.at(0), sizeof(int));
memcpy(&info->data_window[1], &data.at(4), sizeof(int));
memcpy(&info->data_window[2], &data.at(8), sizeof(int));
memcpy(&info->data_window[3], &data.at(12), sizeof(int));
tinyexr::swap4(reinterpret_cast<unsigned int *>(&info->data_window[0]));
tinyexr::swap4(reinterpret_cast<unsigned int *>(&info->data_window[1]));
tinyexr::swap4(reinterpret_cast<unsigned int *>(&info->data_window[2]));
tinyexr::swap4(reinterpret_cast<unsigned int *>(&info->data_window[3]));
has_data_window = true;
if (data.size() < 16) {
// Corrupsed file(Issue #50).
} else {
memcpy(&info->data_window[0], &data.at(0), sizeof(int));
memcpy(&info->data_window[1], &data.at(4), sizeof(int));
memcpy(&info->data_window[2], &data.at(8), sizeof(int));
memcpy(&info->data_window[3], &data.at(12), sizeof(int));
tinyexr::swap4(reinterpret_cast<unsigned int *>(&info->data_window[0]));
tinyexr::swap4(reinterpret_cast<unsigned int *>(&info->data_window[1]));
tinyexr::swap4(reinterpret_cast<unsigned int *>(&info->data_window[2]));
tinyexr::swap4(reinterpret_cast<unsigned int *>(&info->data_window[3]));
has_data_window = true;
}
} else if (attr_name.compare("displayWindow") == 0) {
memcpy(&info->display_window[0], &data.at(0), sizeof(int));
memcpy(&info->display_window[1], &data.at(4), sizeof(int));
@ -10268,7 +10322,7 @@ static int ParseEXRHeader(HeaderInfo *info, bool *empty_header,
}
if (!has_data_window) {
ss_err << "\"dataWindow\" attribute not found in the header."
ss_err << "\"dataWindow\" attribute not found in the header or invalid."
<< std::endl;
}
@ -10333,7 +10387,7 @@ static void ConvertHeader(EXRHeader *exr_header, const HeaderInfo &info) {
#else
strncpy(exr_header->channels[c].name, info.channels[c].name.c_str(), 255);
#endif
// manually add '\0' for safety.
// manually add '\0' for safety.
exr_header->channels[c].name[255] = '\0';
exr_header->channels[c].pixel_type = info.channels[c].pixel_type;
@ -10371,7 +10425,7 @@ static void ConvertHeader(EXRHeader *exr_header, const HeaderInfo &info) {
static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header,
const std::vector<tinyexr::tinyexr_uint64> &offsets,
const unsigned char *head) {
const unsigned char *head, const size_t size) {
int num_channels = exr_header->num_channels;
int num_scanline_blocks = 1;
@ -10412,6 +10466,11 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header,
// 16 byte: tile coordinates
// 4 byte : data size
// ~ : data(uncompressed or compressed)
if (offsets[tile_idx] + sizeof(int) * 5 > size) {
return TINYEXR_ERROR_INVALID_DATA;
}
size_t data_size = size - (offsets[tile_idx] + sizeof(int) * 5);
const unsigned char *data_ptr =
reinterpret_cast<const unsigned char *>(head + offsets[tile_idx]);
@ -10430,7 +10489,10 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header,
memcpy(&data_len, data_ptr + 16,
sizeof(int)); // 16 = sizeof(tile_coordinates)
tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len));
assert(data_len >= 4);
if (data_len < 4 || size_t(data_len) > data_size) {
return TINYEXR_ERROR_INVALID_DATA;
}
// Move to data addr: 20 = 16 + 4;
data_ptr += 20;
@ -10467,11 +10529,18 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header,
#endif
for (int y = 0; y < static_cast<int>(num_blocks); y++) {
size_t y_idx = static_cast<size_t>(y);
const unsigned char *data_ptr =
reinterpret_cast<const unsigned char *>(head + offsets[y_idx]);
if (offsets[y_idx] + sizeof(int) * 2 > size) {
return TINYEXR_ERROR_INVALID_DATA;
}
// 4 byte: scan line
// 4 byte: data size
// ~ : pixel data(uncompressed or compressed)
size_t data_size = size - (offsets[y_idx] + sizeof(int) * 2);
const unsigned char *data_ptr =
reinterpret_cast<const unsigned char *>(head + offsets[y_idx]);
int line_no;
memcpy(&line_no, data_ptr, sizeof(int));
int data_len;
@ -10479,30 +10548,41 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header,
tinyexr::swap4(reinterpret_cast<unsigned int *>(&line_no));
tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len));
if (size_t(data_len) > data_size) {
return TINYEXR_ERROR_INVALID_DATA;
}
int end_line_no = (std::min)(line_no + num_scanline_blocks,
(exr_header->data_window[3] + 1));
int num_lines = end_line_no - line_no;
assert(num_lines > 0);
//assert(num_lines > 0);
// Move to data addr: 8 = 4 + 4;
data_ptr += 8;
// Adjust line_no with data_window.bmin.y
line_no -= exr_header->data_window[1];
if (line_no < 0) {
if (num_lines <= 0) {
invalid_data = true;
} else {
tinyexr::DecodePixelData(
exr_image->images, exr_header->requested_pixel_types, data_ptr,
static_cast<size_t>(data_len), exr_header->compression_type,
exr_header->line_order, data_width, data_height, data_width, y,
line_no, num_lines, static_cast<size_t>(pixel_data_size),
static_cast<size_t>(exr_header->num_custom_attributes),
exr_header->custom_attributes,
static_cast<size_t>(exr_header->num_channels), exr_header->channels,
channel_offset_list);
// Move to data addr: 8 = 4 + 4;
data_ptr += 8;
// Adjust line_no with data_window.bmin.y
line_no -= exr_header->data_window[1];
if (line_no < 0) {
invalid_data = true;
} else {
if (!tinyexr::DecodePixelData(
exr_image->images, exr_header->requested_pixel_types, data_ptr,
static_cast<size_t>(data_len), exr_header->compression_type,
exr_header->line_order, data_width, data_height, data_width, y,
line_no, num_lines, static_cast<size_t>(pixel_data_size),
static_cast<size_t>(exr_header->num_custom_attributes),
exr_header->custom_attributes,
static_cast<size_t>(exr_header->num_channels), exr_header->channels,
channel_offset_list)) {
invalid_data = true;
}
}
}
} // omp parallel
}
@ -10537,7 +10617,7 @@ static bool ReconstructLineOffsets(
for (size_t i = 0; i < n; i++) {
size_t offset = static_cast<size_t>(marker - head);
// Offset should not exceed whole EXR file/data size.
if (offset >= size) {
if ((offset + sizeof(tinyexr::tinyexr_uint64)) >= size) {
return false;
}
@ -10586,8 +10666,15 @@ static int DecodeEXRImage(EXRImage *exr_image, const EXRHeader *exr_header,
int data_width = exr_header->data_window[2] - exr_header->data_window[0] + 1;
int data_height = exr_header->data_window[3] - exr_header->data_window[1] + 1;
if ((data_width < 0) || (data_height < 0)) {
if (err) {
(*err) = "Invalid data window value.";
}
return TINYEXR_ERROR_INVALID_DATA;
}
// Read offset tables.
size_t num_blocks;
size_t num_blocks = 0;
if (exr_header->chunk_count > 0) {
// Use `chunkCount` attribute.
@ -10657,7 +10744,7 @@ static int DecodeEXRImage(EXRImage *exr_image, const EXRHeader *exr_header,
}
}
return DecodeChunk(exr_image, exr_header, offsets, head);
return DecodeChunk(exr_image, exr_header, offsets, head, size);
}
} // namespace tinyexr
@ -10842,8 +10929,8 @@ int ParseEXRHeaderFromMemory(EXRHeader *exr_header, const EXRVersion *version,
}
int LoadEXRFromMemory(float **out_rgba, int *width, int *height,
const unsigned char *memory, size_t size,
const char **err) {
const unsigned char *memory, size_t size,
const char **err) {
if (out_rgba == NULL || memory == NULL) {
if (err) {
(*err) = "Invalid argument.\n";
@ -10866,13 +10953,13 @@ int LoadEXRFromMemory(float **out_rgba, int *width, int *height,
if (ret != TINYEXR_SUCCESS) {
return ret;
}
// Read HALF channel as FLOAT.
for (int i = 0; i < exr_header.num_channels; i++) {
if (exr_header.pixel_types[i] == TINYEXR_PIXELTYPE_HALF) {
exr_header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
}
}
}
InitEXRImage(&exr_image);
ret = LoadEXRImageFromMemory(&exr_image, &exr_header, memory, size, err);
@ -10923,23 +11010,22 @@ int LoadEXRFromMemory(float **out_rgba, int *width, int *height,
}
(*out_rgba) = reinterpret_cast<float *>(
malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) *
static_cast<size_t>(exr_image.height)));
malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) *
static_cast<size_t>(exr_image.height)));
for (int i = 0; i < exr_image.width * exr_image.height; i++) {
(*out_rgba)[4 * i + 0] =
reinterpret_cast<float **>(exr_image.images)[idxR][i];
(*out_rgba)[4 * i + 1] =
reinterpret_cast<float **>(exr_image.images)[idxG][i];
(*out_rgba)[4 * i + 2] =
reinterpret_cast<float **>(exr_image.images)[idxB][i];
if (idxA != -1) {
(*out_rgba)[4 * i + 3] =
reinterpret_cast<float **>(exr_image.images)[idxA][i];
}
else {
(*out_rgba)[4 * i + 3] = 1.0;
}
(*out_rgba)[4 * i + 0] =
reinterpret_cast<float **>(exr_image.images)[idxR][i];
(*out_rgba)[4 * i + 1] =
reinterpret_cast<float **>(exr_image.images)[idxG][i];
(*out_rgba)[4 * i + 2] =
reinterpret_cast<float **>(exr_image.images)[idxB][i];
if (idxA != -1) {
(*out_rgba)[4 * i + 3] =
reinterpret_cast<float **>(exr_image.images)[idxA][i];
} else {
(*out_rgba)[4 * i + 3] = 1.0;
}
}
(*width) = exr_image.width;
@ -11707,7 +11793,12 @@ int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) {
// xSampling: int
// ySampling: int
tinyexr::ReadChannelInfo(channels, data);
if (!tinyexr::ReadChannelInfo(channels, data)) {
if (err) {
(*err) = "Failed to parse channel info.";
}
return TINYEXR_ERROR_INVALID_DATA;
}
num_channels = static_cast<int>(channels.size());
@ -11844,9 +11935,11 @@ int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) {
{
unsigned long dstLen =
static_cast<unsigned long>(pixelOffsetTable.size() * sizeof(int));
tinyexr::DecompressZip(
if (!tinyexr::DecompressZip(
reinterpret_cast<unsigned char *>(&pixelOffsetTable.at(0)), &dstLen,
data_ptr + 28, static_cast<unsigned long>(packedOffsetTableSize));
data_ptr + 28, static_cast<unsigned long>(packedOffsetTableSize))) {
return false;
}
assert(dstLen == pixelOffsetTable.size() * sizeof(int));
for (size_t i = 0; i < static_cast<size_t>(data_width); i++) {
@ -11861,10 +11954,12 @@ int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) {
{
unsigned long dstLen = static_cast<unsigned long>(unpackedSampleDataSize);
if (dstLen) {
tinyexr::DecompressZip(
if (!tinyexr::DecompressZip(
reinterpret_cast<unsigned char *>(&sample_data.at(0)), &dstLen,
data_ptr + 28 + packedOffsetTableSize,
static_cast<unsigned long>(packedSampleDataSize));
static_cast<unsigned long>(packedSampleDataSize))) {
return false;
}
assert(dstLen == static_cast<unsigned long>(unpackedSampleDataSize));
}
}
@ -12390,7 +12485,7 @@ int LoadEXRMultipartImageFromMemory(EXRImage *exr_images,
}
int ret = tinyexr::DecodeChunk(&exr_images[i], exr_headers[i], offset_table,
memory);
memory, size);
if (ret != TINYEXR_SUCCESS) {
return ret;
}