Browse Source

tinyexr: Update to pristine commit e385dad (security update)

Rémi Verschelde 7 years ago
parent
commit
76e5b048d0
2 changed files with 179 additions and 84 deletions
  1. 1 1
      thirdparty/README.md
  2. 178 83
      thirdparty/tinyexr/tinyexr.h

+ 1 - 1
thirdparty/README.md

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

+ 178 - 83
thirdparty/tinyexr/tinyexr.h

@@ -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
 // Returns negative value and may set error string in `err` when there's an
 // error
 // error
 extern int LoadEXRFromMemory(float **out_rgba, int *width, int *height,
 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
 #ifdef __cplusplus
 }
 }
@@ -444,7 +444,8 @@ extern int LoadEXRFromMemory(float **out_rgba, int *width, int *height,
 
 
 #if TINYEXR_USE_MINIZ
 #if TINYEXR_USE_MINIZ
 #else
 #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"
 //#include "zlib.h"
 #endif
 #endif
 
 
@@ -488,6 +489,12 @@ namespace miniz {
 #if __has_warning("-Wcomma")
 #if __has_warning("-Wcomma")
 #pragma clang diagnostic ignored "-Wcomma"
 #pragma clang diagnostic ignored "-Wcomma"
 #endif
 #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
 #endif
 
 
 /* miniz.c v1.15 - public domain deflate/inflate, zlib-subset, ZIP
 /* 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
 #ifdef _MSC_VER
 #pragma warning(pop)
 #pragma warning(pop)
 #endif
 #endif
-
-
 }
 }
 #else
 #else
 
 
@@ -7079,11 +7084,18 @@ static FP16 float_to_half_full(FP32 f) {
 // #define IMF_B44_COMPRESSION 6
 // #define IMF_B44_COMPRESSION 6
 // #define IMF_B44A_COMPRESSION  7
 // #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).
   // Read untile NULL(\0).
   const char *p = ptr;
   const char *p = ptr;
   const char *q = 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);
   (*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));
   memcpy(&data_len, marker, sizeof(uint32_t));
   tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len));
   tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len));
 
 
+  if (data_len == 0) {
+    return false;
+  }
+
   marker += sizeof(uint32_t);
   marker += sizeof(uint32_t);
   size -= sizeof(uint32_t);
   size -= sizeof(uint32_t);
 
 
@@ -7210,7 +7226,7 @@ typedef struct {
   }
   }
 } HeaderInfo;
 } HeaderInfo;
 
 
-static void ReadChannelInfo(std::vector<ChannelInfo> &channels,
+static bool ReadChannelInfo(std::vector<ChannelInfo> &channels,
                             const std::vector<unsigned char> &data) {
                             const std::vector<unsigned char> &data) {
   const char *p = reinterpret_cast<const char *>(&data.at(0));
   const char *p = reinterpret_cast<const char *>(&data.at(0));
 
 
@@ -7219,7 +7235,18 @@ static void ReadChannelInfo(std::vector<ChannelInfo> &channels,
       break;
       break;
     }
     }
     ChannelInfo info;
     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));
     memcpy(&info.pixel_type, p, sizeof(int));
     p += 4;
     p += 4;
@@ -7236,6 +7263,8 @@ static void ReadChannelInfo(std::vector<ChannelInfo> &channels,
 
 
     channels.push_back(info);
     channels.push_back(info);
   }
   }
+
+  return true;
 }
 }
 
 
 static void WriteChannelInfo(std::vector<unsigned char> &data,
 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 */,
                           unsigned long *uncompressed_size /* inout */,
                           const unsigned char *src, unsigned long src_size) {
                           const unsigned char *src, unsigned long src_size) {
   if ((*uncompressed_size) == src_size) {
   if ((*uncompressed_size) == src_size) {
     // Data is not compressed(Issue 40).
     // Data is not compressed(Issue 40).
     memcpy(dst, src, src_size);
     memcpy(dst, src, src_size);
-    return;
+    return true;
   }
   }
   std::vector<unsigned char> tmpBuf(*uncompressed_size);
   std::vector<unsigned char> tmpBuf(*uncompressed_size);
 
 
 #if TINYEXR_USE_MINIZ
 #if TINYEXR_USE_MINIZ
   int ret =
   int ret =
       miniz::mz_uncompress(&tmpBuf.at(0), uncompressed_size, src, src_size);
       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
 #else
   int ret = uncompress(&tmpBuf.at(0), uncompressed_size, src, src_size);
   int ret = uncompress(&tmpBuf.at(0), uncompressed_size, src, src_size);
-  assert(ret == Z_OK);
-  (void)ret;
+  if (Z_OK != ret) {
+    return false;
+  }
 #endif
 #endif
 
 
   //
   //
@@ -7419,6 +7450,8 @@ static void DecompressZip(unsigned char *dst,
         break;
         break;
     }
     }
   }
   }
+
+  return true;
 }
 }
 
 
 // RLE code from OpenEXR --------------------------------------
 // RLE code from OpenEXR --------------------------------------
@@ -7443,7 +7476,6 @@ static void DecompressZip(unsigned char *dst,
                                  // conformant name: _strdup.
                                  // conformant name: _strdup.
 #endif
 #endif
 
 
-
 const int MIN_RUN_LENGTH = 3;
 const int MIN_RUN_LENGTH = 3;
 const int MAX_RUN_LENGTH = 127;
 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 "-Wsign-conversion"
 #pragma clang diagnostic ignored "-Wc++11-extensions"
 #pragma clang diagnostic ignored "-Wc++11-extensions"
 #pragma clang diagnostic ignored "-Wconversion"
 #pragma clang diagnostic ignored "-Wconversion"
+
+#if __has_warning("-Wcast-qual")
+#pragma clang diagnostic ignored "-Wcast-qual"
+#endif
+
 #endif
 #endif
 
 
 //
 //
@@ -8934,7 +8971,6 @@ static void applyLut(const unsigned short lut[USHORT_RANGE],
 #pragma warning(pop)
 #pragma warning(pop)
 #endif
 #endif
 
 
-
 static bool CompressPiz(unsigned char *outPtr, unsigned int *outSize,
 static bool CompressPiz(unsigned char *outPtr, unsigned int *outSize,
                         const unsigned char *inPtr, size_t inSize,
                         const unsigned char *inPtr, size_t inSize,
                         const std::vector<ChannelInfo> &channelInfo,
                         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 int *requested_pixel_types,
                             const unsigned char *data_ptr, size_t data_len,
                             const unsigned char *data_ptr, size_t data_len,
                             int compression_type, int line_order, int width,
                             int compression_type, int line_order, int width,
@@ -9509,6 +9545,7 @@ static void DecodePixelData(/* out */ unsigned char **out_images,
     }
     }
 #else
 #else
     assert(0 && "PIZ is enabled in this build");
     assert(0 && "PIZ is enabled in this build");
+    return false;
 #endif
 #endif
 
 
   } else if (compression_type == TINYEXR_COMPRESSIONTYPE_ZIPS ||
   } 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());
     unsigned long dstLen = static_cast<unsigned long>(outBuf.size());
     assert(dstLen > 0);
     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,
                            &dstLen, data_ptr,
-                           static_cast<unsigned long>(data_len));
+                           static_cast<unsigned long>(data_len))) {
+      return false;
+    }
 
 
     // For ZIP_COMPRESSION:
     // For ZIP_COMPRESSION:
     //   pixel sample data for channel 0 for scanline 0
     //   pixel sample data for channel 0 for scanline 0
@@ -9633,6 +9672,7 @@ static void DecodePixelData(/* out */ unsigned char **out_images,
         }
         }
       } else {
       } else {
         assert(0);
         assert(0);
+        return false;
       }
       }
     }
     }
   } else if (compression_type == TINYEXR_COMPRESSIONTYPE_RLE) {
   } else if (compression_type == TINYEXR_COMPRESSIONTYPE_RLE) {
@@ -9756,6 +9796,7 @@ static void DecodePixelData(/* out */ unsigned char **out_images,
         }
         }
       } else {
       } else {
         assert(0);
         assert(0);
+        return false;
       }
       }
     }
     }
   } else if (compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) {
   } 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,
     if (!FindZFPCompressionParam(&zfp_compression_param, attributes,
                                  num_attributes)) {
                                  num_attributes)) {
       assert(0);
       assert(0);
-      return;
+      return false;
     }
     }
 
 
     // Allocate original data size.
     // Allocate original data size.
@@ -9818,6 +9859,7 @@ static void DecodePixelData(/* out */ unsigned char **out_images,
         }
         }
       } else {
       } else {
         assert(0);
         assert(0);
+        return false;
       }
       }
     }
     }
 #else
 #else
@@ -9825,6 +9867,7 @@ static void DecodePixelData(/* out */ unsigned char **out_images,
     (void)num_attributes;
     (void)num_attributes;
     (void)num_channels;
     (void)num_channels;
     assert(0);
     assert(0);
+    return false;
 #endif
 #endif
   } else if (compression_type == TINYEXR_COMPRESSIONTYPE_NONE) {
   } else if (compression_type == TINYEXR_COMPRESSIONTYPE_NONE) {
     for (size_t c = 0; c < num_channels; c++) {
     for (size_t c = 0; c < num_channels; c++) {
@@ -9873,6 +9916,7 @@ static void DecodePixelData(/* out */ unsigned char **out_images,
           }
           }
         } else {
         } else {
           assert(0);
           assert(0);
+          return false;
         }
         }
       } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) {
       } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) {
         const float *line_ptr = reinterpret_cast<const 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(
 static void DecodeTiledPixelData(
@@ -10161,7 +10207,12 @@ static int ParseEXRHeader(HeaderInfo *info, bool *empty_header,
       // xSampling: int
       // xSampling: int
       // ySampling: 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 (info->channels.size() < 1) {
         if (err) {
         if (err) {
@@ -10173,16 +10224,19 @@ static int ParseEXRHeader(HeaderInfo *info, bool *empty_header,
       has_channels = true;
       has_channels = true;
 
 
     } else if (attr_name.compare("dataWindow") == 0) {
     } 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) {
     } else if (attr_name.compare("displayWindow") == 0) {
       memcpy(&info->display_window[0], &data.at(0), sizeof(int));
       memcpy(&info->display_window[0], &data.at(0), sizeof(int));
       memcpy(&info->display_window[1], &data.at(4), 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) {
     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;
              << std::endl;
     }
     }
 
 
@@ -10333,7 +10387,7 @@ static void ConvertHeader(EXRHeader *exr_header, const HeaderInfo &info) {
 #else
 #else
     strncpy(exr_header->channels[c].name, info.channels[c].name.c_str(), 255);
     strncpy(exr_header->channels[c].name, info.channels[c].name.c_str(), 255);
 #endif
 #endif
-	// manually add '\0' for safety.
+    // manually add '\0' for safety.
     exr_header->channels[c].name[255] = '\0';
     exr_header->channels[c].name[255] = '\0';
 
 
     exr_header->channels[c].pixel_type = info.channels[c].pixel_type;
     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,
 static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header,
                        const std::vector<tinyexr::tinyexr_uint64> &offsets,
                        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_channels = exr_header->num_channels;
 
 
   int num_scanline_blocks = 1;
   int num_scanline_blocks = 1;
@@ -10412,6 +10466,11 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header,
       // 16 byte: tile coordinates
       // 16 byte: tile coordinates
       // 4 byte : data size
       // 4 byte : data size
       // ~      : data(uncompressed or compressed)
       // ~      : 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 =
       const unsigned char *data_ptr =
           reinterpret_cast<const unsigned char *>(head + offsets[tile_idx]);
           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,
       memcpy(&data_len, data_ptr + 16,
              sizeof(int));  // 16 = sizeof(tile_coordinates)
              sizeof(int));  // 16 = sizeof(tile_coordinates)
       tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len));
       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;
       // Move to data addr: 20 = 16 + 4;
       data_ptr += 20;
       data_ptr += 20;
@@ -10467,11 +10529,18 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header,
 #endif
 #endif
     for (int y = 0; y < static_cast<int>(num_blocks); y++) {
     for (int y = 0; y < static_cast<int>(num_blocks); y++) {
       size_t y_idx = static_cast<size_t>(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: scan line
       // 4 byte: data size
       // 4 byte: data size
       // ~     : pixel data(uncompressed or compressed)
       // ~     : 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;
       int line_no;
       memcpy(&line_no, data_ptr, sizeof(int));
       memcpy(&line_no, data_ptr, sizeof(int));
       int data_len;
       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 *>(&line_no));
       tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len));
       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,
       int end_line_no = (std::min)(line_no + num_scanline_blocks,
                                    (exr_header->data_window[3] + 1));
                                    (exr_header->data_window[3] + 1));
 
 
       int num_lines = end_line_no - line_no;
       int num_lines = end_line_no - line_no;
-      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];
+      //assert(num_lines > 0);
 
 
-      if (line_no < 0) {
+      if (num_lines <= 0) {
         invalid_data = true;
         invalid_data = true;
       } else {
       } 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
     }  // omp parallel
   }
   }
@@ -10537,7 +10617,7 @@ static bool ReconstructLineOffsets(
   for (size_t i = 0; i < n; i++) {
   for (size_t i = 0; i < n; i++) {
     size_t offset = static_cast<size_t>(marker - head);
     size_t offset = static_cast<size_t>(marker - head);
     // Offset should not exceed whole EXR file/data size.
     // Offset should not exceed whole EXR file/data size.
-    if (offset >= size) {
+    if ((offset + sizeof(tinyexr::tinyexr_uint64)) >= size) {
       return false;
       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_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;
   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.
   // Read offset tables.
-  size_t num_blocks;
+  size_t num_blocks = 0;
 
 
   if (exr_header->chunk_count > 0) {
   if (exr_header->chunk_count > 0) {
     // Use `chunkCount` attribute.
     // 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
 }  // namespace tinyexr
@@ -10842,8 +10929,8 @@ int ParseEXRHeaderFromMemory(EXRHeader *exr_header, const EXRVersion *version,
 }
 }
 
 
 int LoadEXRFromMemory(float **out_rgba, int *width, int *height,
 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 (out_rgba == NULL || memory == NULL) {
     if (err) {
     if (err) {
       (*err) = "Invalid argument.\n";
       (*err) = "Invalid argument.\n";
@@ -10866,13 +10953,13 @@ int LoadEXRFromMemory(float **out_rgba, int *width, int *height,
   if (ret != TINYEXR_SUCCESS) {
   if (ret != TINYEXR_SUCCESS) {
     return ret;
     return ret;
   }
   }
-  
+
   // Read HALF channel as FLOAT.
   // Read HALF channel as FLOAT.
   for (int i = 0; i < exr_header.num_channels; i++) {
   for (int i = 0; i < exr_header.num_channels; i++) {
     if (exr_header.pixel_types[i] == TINYEXR_PIXELTYPE_HALF) {
     if (exr_header.pixel_types[i] == TINYEXR_PIXELTYPE_HALF) {
       exr_header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
       exr_header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
     }
     }
-  }  
+  }
 
 
   InitEXRImage(&exr_image);
   InitEXRImage(&exr_image);
   ret = LoadEXRImageFromMemory(&exr_image, &exr_header, memory, size, err);
   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 *>(
   (*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++) {
   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;
   (*width) = exr_image.width;
@@ -11707,7 +11793,12 @@ int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) {
       // xSampling: int
       // xSampling: int
       // ySampling: 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());
       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 =
       unsigned long dstLen =
           static_cast<unsigned long>(pixelOffsetTable.size() * sizeof(int));
           static_cast<unsigned long>(pixelOffsetTable.size() * sizeof(int));
-      tinyexr::DecompressZip(
+      if (!tinyexr::DecompressZip(
           reinterpret_cast<unsigned char *>(&pixelOffsetTable.at(0)), &dstLen,
           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));
       assert(dstLen == pixelOffsetTable.size() * sizeof(int));
       for (size_t i = 0; i < static_cast<size_t>(data_width); i++) {
       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);
       unsigned long dstLen = static_cast<unsigned long>(unpackedSampleDataSize);
       if (dstLen) {
       if (dstLen) {
-        tinyexr::DecompressZip(
+        if (!tinyexr::DecompressZip(
             reinterpret_cast<unsigned char *>(&sample_data.at(0)), &dstLen,
             reinterpret_cast<unsigned char *>(&sample_data.at(0)), &dstLen,
             data_ptr + 28 + packedOffsetTableSize,
             data_ptr + 28 + packedOffsetTableSize,
-            static_cast<unsigned long>(packedSampleDataSize));
+            static_cast<unsigned long>(packedSampleDataSize))) {
+          return false;
+        }
         assert(dstLen == static_cast<unsigned long>(unpackedSampleDataSize));
         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,
     int ret = tinyexr::DecodeChunk(&exr_images[i], exr_headers[i], offset_table,
-                                   memory);
+                                   memory, size);
     if (ret != TINYEXR_SUCCESS) {
     if (ret != TINYEXR_SUCCESS) {
       return ret;
       return ret;
     }
     }