XFA: remove unsafe exif parsing code
authorTom Sepez <tsepez@chromium.org>
Thu, 29 Oct 2015 16:51:03 +0000 (09:51 -0700)
committerTom Sepez <tsepez@chromium.org>
Thu, 29 Oct 2015 16:51:03 +0000 (09:51 -0700)
Fortunately, this could only be called with a null buffer,
so none of unchecked lengths could be used.  The remaining
use of the CFX_/IFX_DIBAttributeEx class is as a table, so
put one directly in the CFX_DIBAttribute.

Fix a "register" warning along the way.

R=dsinclair@chromium.org

Review URL: https://codereview.chromium.org/1425983002 .

core/include/fxcodec/fx_codec.h
core/src/fxcodec/codec/codec_int.h
core/src/fxcodec/codec/fx_codec.cpp
core/src/fxcodec/codec/fx_codec_tiff.cpp

index 3ac9434..8eacbb2 100644 (file)
@@ -7,6 +7,7 @@
 #ifndef CORE_INCLUDE_FXCODEC_FX_CODEC_H_
 #define CORE_INCLUDE_FXCODEC_FX_CODEC_H_
 
+#include <map>
 #include <vector>
 
 #include "../../../third_party/base/nonstd_unique_ptr.h"
@@ -502,37 +503,24 @@ void AdobeCMYK_to_sRGB1(uint8_t c,
                         uint8_t& G,
                         uint8_t& B);
 FX_BOOL MD5ComputeID(const void* buf, FX_DWORD dwSize, uint8_t ID[16]);
+
 class CFX_DIBAttribute {
  public:
   CFX_DIBAttribute();
   ~CFX_DIBAttribute();
 
   int32_t m_nXDPI;
-
   int32_t m_nYDPI;
-
   FX_FLOAT m_fAspectRatio;
-
   FX_WORD m_wDPIUnit;
-
   CFX_ByteString m_strAuthor;
-
   uint8_t m_strTime[20];
-
   int32_t m_nGifLeft;
   int32_t m_nGifTop;
-
   FX_DWORD* m_pGifLocalPalette;
-
   FX_DWORD m_nGifLocalPalNum;
-
   int32_t m_nBmpCompressType;
-  class IFX_DIBAttributeExif* m_pExif;
-};
-class IFX_DIBAttributeExif {
- public:
-  virtual ~IFX_DIBAttributeExif(){};
-  virtual FX_BOOL GetInfo(FX_WORD tag, void* val) = 0;
+  std::map<FX_DWORD, void*> m_Exif;
 };
 
 FX_BOOL FaxSkipEOL(const uint8_t* src_buf, int bitsize, int& bitpos);
index 510d0ab..3671641 100644 (file)
@@ -385,38 +385,6 @@ class CCodec_Jbig2Module : public ICodec_Jbig2Module {
                                 IFX_Pause* pPause) override;
   void DestroyJbig2Context(void* pJbig2Context) override;
 };
-class CFX_DIBAttributeExif : public IFX_DIBAttributeExif {
- public:
-  CFX_DIBAttributeExif();
-  ~CFX_DIBAttributeExif();
-  virtual FX_BOOL GetInfo(FX_WORD tag, void* val);
-
-  FX_BOOL ParseExif(CFX_MapPtrTemplate<FX_DWORD, uint8_t*>* pHead,
-                    uint8_t* data,
-                    FX_DWORD len,
-                    CFX_MapPtrTemplate<FX_DWORD, uint8_t*>* pVal);
-
-  typedef FX_WORD (*_Read2Bytes)(uint8_t* data);
-  typedef FX_DWORD (*_Read4Bytes)(uint8_t* data);
-  uint8_t* ParseExifIFH(uint8_t* data,
-                        FX_DWORD len,
-                        _Read2Bytes* pReadWord,
-                        _Read4Bytes* pReadDword);
-  FX_BOOL ParseExifIFD(CFX_MapPtrTemplate<FX_DWORD, uint8_t*>* pMap,
-                       uint8_t* data,
-                       FX_DWORD len);
-
-  uint8_t* m_pExifData;
-
-  FX_DWORD m_dwExifDataLen;
-
-  void clear();
-  _Read2Bytes m_readWord;
-  _Read4Bytes m_readDword;
-  CFX_MapPtrTemplate<FX_DWORD, uint8_t*> m_TagHead;
-  CFX_MapPtrTemplate<FX_DWORD, uint8_t*> m_TagVal;
-};
-
 struct DecodeData {
  public:
   DecodeData(unsigned char* src_data, OPJ_SIZE_T src_size)
index 622dab0..a443b75 100644 (file)
@@ -257,347 +257,23 @@ FX_BOOL CCodec_BasicModule::A85Encode(const uint8_t* src_buf,
                                       FX_DWORD& dest_size) {
   return FALSE;
 }
-CFX_DIBAttribute::CFX_DIBAttribute() {
-  FXSYS_memset(this, 0, sizeof(CFX_DIBAttribute));
-  m_nXDPI = -1;
-  m_nYDPI = -1;
-  m_fAspectRatio = -1.0f;
-  m_pExif = new CFX_DIBAttributeExif;
+CFX_DIBAttribute::CFX_DIBAttribute()
+    : m_nXDPI(-1),
+      m_nYDPI(-1),
+      m_fAspectRatio(-1.0f),
+      m_wDPIUnit(0),
+      m_nGifLeft(0),
+      m_nGifTop(0),
+      m_pGifLocalPalette(nullptr),
+      m_nGifLocalPalNum(0),
+      m_nBmpCompressType(0) {
+  FXSYS_memset(m_strTime, 0, sizeof(m_strTime));
 }
 CFX_DIBAttribute::~CFX_DIBAttribute() {
-  if (m_pExif) {
-    delete m_pExif;
-  }
-}
-CFX_DIBAttributeExif::CFX_DIBAttributeExif() {
-  m_pExifData = NULL;
-  m_dwExifDataLen = 0;
-}
-CFX_DIBAttributeExif::~CFX_DIBAttributeExif() {
-  clear();
-}
-void CFX_DIBAttributeExif::clear() {
-  if (m_pExifData) {
-    FX_Free(m_pExifData);
-  }
-  m_pExifData = NULL;
-  FX_DWORD key = 0;
-  uint8_t* buf = NULL;
-  FX_POSITION pos = NULL;
-  pos = m_TagHead.GetStartPosition();
-  while (pos) {
-    m_TagHead.GetNextAssoc(pos, key, buf);
-    if (buf) {
-      FX_Free(buf);
-    }
-  }
-  m_TagHead.RemoveAll();
-  pos = m_TagVal.GetStartPosition();
-  while (pos) {
-    m_TagVal.GetNextAssoc(pos, key, buf);
-    if (buf) {
-      FX_Free(buf);
-    }
-  }
-  m_TagVal.RemoveAll();
-}
-static FX_WORD _Read2BytesL(uint8_t* data) {
-  ASSERT(data);
-  return data[0] | (data[1] << 8);
-}
-static FX_WORD _Read2BytesB(uint8_t* data) {
-  ASSERT(data);
-  return data[1] | (data[0] << 8);
-}
-static FX_DWORD _Read4BytesL(uint8_t* data) {
-  return _Read2BytesL(data) | (_Read2BytesL(data + 2) << 16);
-}
-static FX_DWORD _Read4BytesB(uint8_t* data) {
-  return _Read2BytesB(data + 2) | (_Read2BytesB(data) << 16);
-}
-typedef FX_WORD (*_Read2Bytes)(uint8_t* data);
-typedef FX_DWORD (*_Read4Bytes)(uint8_t* data);
-typedef void (*_Write2Bytes)(uint8_t* data, FX_WORD val);
-typedef void (*_Write4Bytes)(uint8_t* data, FX_DWORD val);
-uint8_t* CFX_DIBAttributeExif::ParseExifIFH(uint8_t* data,
-                                            FX_DWORD len,
-                                            _Read2Bytes* pReadWord,
-                                            _Read4Bytes* pReadDword) {
-  if (len > 8) {
-    FX_BOOL tag = FALSE;
-    if (FXSYS_memcmp(data, "\x49\x49\x2a\x00", 4) == 0) {
-      if (pReadWord) {
-        *pReadWord = _Read2BytesL;
-      }
-      if (pReadDword) {
-        *pReadDword = _Read4BytesL;
-      }
-      tag = TRUE;
-    } else if (FXSYS_memcmp(data, "\x4d\x4d\x00\x2a", 4) == 0) {
-      if (pReadWord) {
-        *pReadWord = _Read2BytesB;
-      }
-      if (pReadDword) {
-        *pReadDword = _Read4BytesB;
-      }
-      tag = TRUE;
-    }
-    if (tag) {
-      data += 4;
-      if (pReadDword) {
-        data += (*pReadDword)(data)-4;
-      } else {
-        data += 4;
-      }
-    }
-  }
-  return data;
-}
-FX_BOOL CFX_DIBAttributeExif::ParseExifIFD(
-    CFX_MapPtrTemplate<FX_DWORD, uint8_t*>* pMap,
-    uint8_t* data,
-    FX_DWORD len) {
-  if (pMap && data) {
-    if (len > 8) {
-      FX_WORD wTagNum = m_readWord(data);
-      data += 2;
-      FX_DWORD wTag;
-      uint8_t* buf;
-      while (wTagNum--) {
-        wTag = m_readWord(data);
-        data += 2;
-        if (!pMap->Lookup(wTag, buf)) {
-          buf = FX_Alloc(uint8_t, 10);
-          if (buf == NULL) {
-            return FALSE;
-          }
-          FXSYS_memcpy(buf, data, 10);
-          pMap->SetAt(wTag, buf);
-        }
-        data += 10;
-      }
-      FX_DWORD dwIFDOffset;
-      dwIFDOffset = m_readDword(data);
-      while (dwIFDOffset && dwIFDOffset < len) {
-        data = m_pExifData + dwIFDOffset;
-        wTagNum = m_readWord(data);
-        data += 2;
-        while (wTagNum--) {
-          wTag = m_readWord(data);
-          data += 2;
-          if (!pMap->Lookup(wTag, buf)) {
-            buf = FX_Alloc(uint8_t, 10);
-            if (buf == NULL) {
-              return FALSE;
-            }
-            FXSYS_memcpy(buf, data, 10);
-            pMap->SetAt(wTag, buf);
-          }
-          data += 10;
-        }
-        dwIFDOffset = m_readDword(data);
-      }
-      return TRUE;
-    }
-  }
-  return FALSE;
-}
-enum FX_ExifDataType {
-  FX_UnsignedByte = 1,
-  FX_AscString,
-  FX_UnsignedShort,
-  FX_UnsignedLong,
-  FX_UnsignedRation,
-  FX_SignedByte,
-  FX_Undefined,
-  FX_SignedShort,
-  FX_SignedLong,
-  FX_SignedRation,
-  FX_SignedFloat,
-  FX_DoubleFloat
-};
-FX_BOOL CFX_DIBAttributeExif::ParseExif(
-    CFX_MapPtrTemplate<FX_DWORD, uint8_t*>* pHead,
-    uint8_t* data,
-    FX_DWORD len,
-    CFX_MapPtrTemplate<FX_DWORD, uint8_t*>* pVal) {
-  if (pHead && data && pVal) {
-    if (len > 8) {
-      uint8_t* old_data = data;
-      data = ParseExifIFH(data, len, &m_readWord, &m_readDword);
-      if (data == old_data) {
-        return FALSE;
-      }
-      if (pHead->GetCount() == 0) {
-        if (!ParseExifIFD(pHead, data, len)) {
-          return FALSE;
-        }
-      }
-      FX_DWORD dwModuleNum;
-      FX_WORD type;
-      FX_DWORD dwSize;
-      FX_DWORD tag;
-      uint8_t* head;
-      FX_POSITION pos = pHead->GetStartPosition();
-      while (pos) {
-        pHead->GetNextAssoc(pos, tag, head);
-        uint8_t* val = NULL;
-        uint8_t* buf = NULL;
-        uint8_t* temp = NULL;
-        int i;
-        if (head) {
-          type = m_readWord(head);
-          head += 2;
-          dwModuleNum = m_readDword(head);
-          head += 4;
-          switch (type) {
-            case FX_UnsignedByte:
-            case FX_AscString:
-            case FX_SignedByte:
-            case FX_Undefined:
-              dwSize = dwModuleNum;
-              val = FX_Alloc(uint8_t, dwSize);
-              if (val == NULL) {
-                return FALSE;
-              }
-              if (dwSize > 4) {
-                FXSYS_memcpy(val, old_data + m_readDword(head), dwSize);
-              } else {
-                FXSYS_memcpy(val, head, dwSize);
-              }
-              break;
-            case FX_UnsignedShort:
-            case FX_SignedShort:
-              dwSize = dwModuleNum << 1;
-              val = FX_Alloc(uint8_t, dwSize);
-              if (val == NULL) {
-                return FALSE;
-              }
-              if (dwSize > 4) {
-                FXSYS_memcpy(val, old_data + m_readDword(head), dwSize);
-              } else {
-                FXSYS_memcpy(val, head, dwSize);
-              }
-              buf = val;
-              for (i = 0; i < (int)dwModuleNum; i++) {
-                *(FX_WORD*)buf = m_readWord(buf);
-                buf += 2;
-              }
-              break;
-            case FX_UnsignedLong:
-            case FX_SignedLong:
-            case FX_SignedFloat:
-              dwSize = dwModuleNum << 2;
-              val = FX_Alloc(uint8_t, dwSize);
-              if (val == NULL) {
-                return FALSE;
-              }
-              if (dwSize > 4) {
-                FXSYS_memcpy(val, old_data + m_readDword(head), dwSize);
-              } else {
-                FXSYS_memcpy(val, head, dwSize);
-              }
-              buf = val;
-              for (i = 0; i < (int)dwModuleNum; i++) {
-                *(FX_DWORD*)buf = m_readDword(buf);
-                buf += 4;
-              }
-              break;
-            case FX_UnsignedRation:
-            case FX_SignedRation: {
-              dwSize = dwModuleNum << 3;
-              buf = FX_Alloc(uint8_t, dwSize);
-              if (buf == NULL) {
-                return FALSE;
-              }
-              if (dwSize > 4) {
-                FXSYS_memcpy(buf, old_data + m_readDword(head), dwSize);
-              } else {
-                FXSYS_memcpy(buf, head, dwSize);
-              }
-              temp = buf;
-              val = FX_Alloc(uint8_t, dwSize / 2);
-              if (val == NULL) {
-                FX_Free(buf);
-                return FALSE;
-              }
-              for (i = 0; i < (int)dwModuleNum; i++) {
-                *(FX_DWORD*)temp = m_readDword(temp);
-                *(FX_DWORD*)(temp + 4) = m_readDword(temp + 4);
-                FX_DWORD* lNumerator = (FX_DWORD*)temp;
-                FX_DWORD* lNenominator = (FX_DWORD*)(temp + 4);
-                *(FX_FLOAT*)(val + i * 4) =
-                    (FX_FLOAT)(*lNumerator) / (FX_FLOAT)(*lNenominator);
-                temp += 8;
-              }
-              FX_Free(buf);
-            } break;
-            case FX_DoubleFloat:
-              dwSize = dwModuleNum << 3;
-              val = FX_Alloc(uint8_t, dwSize);
-              if (val == NULL) {
-                return FALSE;
-              }
-              if (dwSize > 4) {
-                FXSYS_memcpy(val, old_data + m_readDword(head), dwSize);
-              } else {
-                FXSYS_memcpy(val, head, dwSize);
-              }
-              buf = val;
-              for (i = 0; i < (int)dwModuleNum; i++) {
-                *(FX_DWORD*)buf = m_readDword(buf);
-                *(FX_DWORD*)(buf + 4) = m_readDword(buf + 4);
-                buf += 8;
-              }
-              break;
-            default:
-              return FALSE;
-          }
-        }
-        pVal->SetAt(tag, val);
-      }
-      return TRUE;
-    }
-  }
-  return FALSE;
-}
-#define FXEXIF_INFOCONVERT(T) \
-  {                           \
-    T* src = (T*)ptr;         \
-    T* dst = (T*)val;         \
-    *dst = *src;              \
-  }
-FX_BOOL CFX_DIBAttributeExif::GetInfo(FX_WORD tag, void* val) {
-  if (m_TagVal.GetCount() == 0) {
-    if (!ParseExif(&m_TagHead, m_pExifData, m_dwExifDataLen, &m_TagVal)) {
-      return FALSE;
-    }
-  }
-  uint8_t* ptr = NULL;
-  if (m_TagVal.Lookup(tag, ptr)) {
-    switch (tag) {
-      case EXIFTAG_USHORT_RESUNIT:
-        FXEXIF_INFOCONVERT(FX_WORD);
-        {
-          FX_WORD* ptr = (FX_WORD*)val;
-          *ptr -= 1;
-        }
-        break;
-      case EXIFTAG_FLOAT_DPIX:
-      case EXIFTAG_FLOAT_DPIY:
-        FXEXIF_INFOCONVERT(FX_FLOAT);
-        break;
-      case EXIFTAG_USHORT_ORIENTATION:
-        FXEXIF_INFOCONVERT(FX_WORD);
-        break;
-      default: {
-        uint8_t** dst = (uint8_t**)val;
-        *dst = ptr;
-      }
-    }
-  }
-  return TRUE;
+  for (const auto& pair : m_Exif)
+    FX_Free(pair.second);
 }
+
 class CCodec_RLScanlineDecoder : public CCodec_ScanlineDecoder {
  public:
   CCodec_RLScanlineDecoder();
index 1f289bb..1efd2fb 100644 (file)
@@ -256,42 +256,36 @@ void CCodec_TiffContext::GetFrames(int32_t& frames) {
     }                                        \\r
   }                                          \\r
   (key) = NULL;\r
+\r
+namespace {\r
+\r
 template <class T>\r
-static FX_BOOL Tiff_Exif_GetInfo(TIFF* tif_ctx,\r
-                                 ttag_t tag,\r
-                                 CFX_DIBAttributeExif* pExif) {\r
-  uint8_t* key = NULL;\r
-  T val = (T)0;\r
+FX_BOOL Tiff_Exif_GetInfo(TIFF* tif_ctx, ttag_t tag, CFX_DIBAttribute* pAttr) {\r
+  T val = 0;\r
   TIFFGetField(tif_ctx, tag, &val);\r
-  if (val) {\r
-    (key) = FX_Alloc(uint8_t, sizeof(T));\r
-    if ((key) == NULL) {\r
-      return FALSE;\r
-    }\r
-    T* ptr = (T*)(key);\r
-    *ptr = val;\r
-    pExif->m_TagVal.SetAt(tag, (key));\r
-    return TRUE;\r
-  }\r
-  return FALSE;\r
+  if (!val)\r
+    return FALSE;\r
+  T* ptr = FX_Alloc(T, 1);\r
+  *ptr = val;\r
+  pAttr->m_Exif[tag] = (void*)ptr;\r
+  return TRUE;\r
 }\r
-static void Tiff_Exif_GetStringInfo(TIFF* tif_ctx,\r
-                                    ttag_t tag,\r
-                                    CFX_DIBAttributeExif* pExif) {\r
-  FX_CHAR* buf = NULL;\r
-  uint8_t* key = NULL;\r
+void Tiff_Exif_GetStringInfo(TIFF* tif_ctx,\r
+                             ttag_t tag,\r
+                             CFX_DIBAttribute* pAttr) {\r
+  FX_CHAR* buf = nullptr;\r
   TIFFGetField(tif_ctx, tag, &buf);\r
-  if (buf) {\r
-    int32_t size = (int32_t)FXSYS_strlen(buf);\r
-    (key) = FX_Alloc(uint8_t, size + 1);\r
-    if ((key) == NULL) {\r
-      return;\r
-    }\r
-    FXSYS_memcpy((key), buf, size);\r
-    key[size] = 0;\r
-    pExif->m_TagVal.SetAt(tag, (key));\r
-  }\r
+  if (!buf)\r
+    return;\r
+  FX_STRSIZE size = FXSYS_strlen(buf);\r
+  uint8_t* ptr = FX_Alloc(uint8_t, size + 1);\r
+  FXSYS_memcpy(ptr, buf, size);\r
+  ptr[size] = 0;\r
+  pAttr->m_Exif[tag] = ptr;\r
 }\r
+\r
+}  // namespace\r
+\r
 FX_BOOL CCodec_TiffContext::LoadFrameInfo(int32_t frame,\r
                                           FX_DWORD& width,\r
                                           FX_DWORD& height,\r
@@ -322,22 +316,20 @@ FX_BOOL CCodec_TiffContext::LoadFrameInfo(int32_t frame,
                      &pAttribute->m_wDPIUnit)) {\r
       pAttribute->m_wDPIUnit -= 1;\r
     }\r
-    CFX_DIBAttributeExif* pExif = (CFX_DIBAttributeExif*)pAttribute->m_pExif;\r
-    pExif->clear();\r
-    Tiff_Exif_GetInfo<FX_WORD>(tif_ctx, TIFFTAG_ORIENTATION, pExif);\r
-    if (Tiff_Exif_GetInfo<FX_FLOAT>(tif_ctx, TIFFTAG_XRESOLUTION, pExif)) {\r
-      FX_FLOAT fDpi = 0;\r
-      pExif->GetInfo(TIFFTAG_XRESOLUTION, &fDpi);\r
+    Tiff_Exif_GetInfo<FX_WORD>(tif_ctx, TIFFTAG_ORIENTATION, pAttribute);\r
+    if (Tiff_Exif_GetInfo<FX_FLOAT>(tif_ctx, TIFFTAG_XRESOLUTION, pAttribute)) {\r
+      void* val = pAttribute->m_Exif[TIFFTAG_XRESOLUTION];\r
+      FX_FLOAT fDpi = val ? *reinterpret_cast<FX_FLOAT*>(val) : 0;\r
       pAttribute->m_nXDPI = (int32_t)(fDpi + 0.5f);\r
     }\r
-    if (Tiff_Exif_GetInfo<FX_FLOAT>(tif_ctx, TIFFTAG_YRESOLUTION, pExif)) {\r
-      FX_FLOAT fDpi = 0;\r
-      pExif->GetInfo(TIFFTAG_YRESOLUTION, &fDpi);\r
+    if (Tiff_Exif_GetInfo<FX_FLOAT>(tif_ctx, TIFFTAG_YRESOLUTION, pAttribute)) {\r
+      void* val = pAttribute->m_Exif[TIFFTAG_YRESOLUTION];\r
+      FX_FLOAT fDpi = val ? *reinterpret_cast<FX_FLOAT*>(val) : 0;\r
       pAttribute->m_nYDPI = (int32_t)(fDpi + 0.5f);\r
     }\r
-    Tiff_Exif_GetStringInfo(tif_ctx, TIFFTAG_IMAGEDESCRIPTION, pExif);\r
-    Tiff_Exif_GetStringInfo(tif_ctx, TIFFTAG_MAKE, pExif);\r
-    Tiff_Exif_GetStringInfo(tif_ctx, TIFFTAG_MODEL, pExif);\r
+    Tiff_Exif_GetStringInfo(tif_ctx, TIFFTAG_IMAGEDESCRIPTION, pAttribute);\r
+    Tiff_Exif_GetStringInfo(tif_ctx, TIFFTAG_MAKE, pAttribute);\r
+    Tiff_Exif_GetStringInfo(tif_ctx, TIFFTAG_MODEL, pAttribute);\r
   }\r
   bpc = tif_bpc;\r
   if (tif_rps > height) {\r
@@ -346,9 +338,8 @@ FX_BOOL CCodec_TiffContext::LoadFrameInfo(int32_t frame,
   return TRUE;\r
 }\r
 void _TiffBGRA2RGBA(uint8_t* pBuf, int32_t pixel, int32_t spp) {\r
-  register uint8_t tmp;\r
   for (int32_t n = 0; n < pixel; n++) {\r
-    tmp = pBuf[0];\r
+    uint8_t tmp = pBuf[0];\r
     pBuf[0] = pBuf[2];\r
     pBuf[2] = tmp;\r
     pBuf += spp;\r