Fix include paths for fx_system.h
[pdfium.git] / core / src / fxcodec / jbig2 / JBig2_Context.cpp
index 232bbf2..ca895e5 100644 (file)
@@ -4,9 +4,17 @@
 
 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
 
-#include <list>
 #include "JBig2_Context.h"
 
+#include <list>
+
+#include "JBig2_GrdProc.h"
+#include "JBig2_GrrdProc.h"
+#include "JBig2_HtrdProc.h"
+#include "JBig2_PddProc.h"
+#include "JBig2_SddProc.h"
+#include "JBig2_TrdProc.h"
+
 // Implement a very small least recently used (LRU) cache. It is very
 // common for a JBIG2 dictionary to span multiple pages in a PDF file,
 // and we do not want to decode the same dictionary over and over
 // list keeps track of the freshness of entries, with freshest ones
 // at the front. Even a tiny cache size like 2 makes a dramatic
 // difference for typical JBIG2 documents.
-const int kSymbolDictCacheMaxSize = 2;
+//
+// Disabled until we can figure out how to clear cache between documents.
+// https://code.google.com/p/pdfium/issues/detail?id=207
+#define DISABLE_SYMBOL_CACHE
+#ifndef DISABLE_SYMBOL_CACHE
+static const int kSymbolDictCacheMaxSize = 2;
+#endif
 
 CJBig2_Context* CJBig2_Context::CreateContext(
     const uint8_t* pGlobalData,
     FX_DWORD dwGlobalLength,
     const uint8_t* pData,
     FX_DWORD dwLength,
-    int32_t nStreamType,
     std::list<CJBig2_CachePair>* pSymbolDictCache,
     IFX_Pause* pPause) {
   return new CJBig2_Context(pGlobalData, dwGlobalLength, pData, dwLength,
-                            nStreamType, pSymbolDictCache, pPause);
+                            pSymbolDictCache, pPause);
 }
+
 void CJBig2_Context::DestroyContext(CJBig2_Context* pContext) {
   delete pContext;
 }
+
 CJBig2_Context::CJBig2_Context(const uint8_t* pGlobalData,
                                FX_DWORD dwGlobalLength,
                                const uint8_t* pData,
                                FX_DWORD dwLength,
-                               int32_t nStreamType,
                                std::list<CJBig2_CachePair>* pSymbolDictCache,
-                               IFX_Pause* pPause) {
+                               IFX_Pause* pPause)
+    : m_nSegmentDecoded(0),
+      m_bInPage(false),
+      m_bBufSpecified(false),
+      m_PauseStep(10),
+      m_pPause(pPause),
+      m_ProcessingStatus(FXCODEC_STATUS_FRAME_READY),
+      m_pArithDecoder(NULL),
+      m_gbContext(NULL),
+      m_dwOffset(0),
+      m_pSymbolDictCache(pSymbolDictCache) {
   if (pGlobalData && (dwGlobalLength > 0)) {
-    m_pGlobalContext =
-        new CJBig2_Context(NULL, 0, pGlobalData, dwGlobalLength,
-                           JBIG2_EMBED_STREAM, pSymbolDictCache, pPause);
+    m_pGlobalContext = new CJBig2_Context(
+        nullptr, 0, pGlobalData, dwGlobalLength, pSymbolDictCache, pPause);
   } else {
-    m_pGlobalContext = NULL;
-  }
-  m_pStream = new CJBig2_BitStream(pData, dwLength);
-  m_nStreamType = nStreamType;
-  m_nState = JBIG2_OUT_OF_PAGE;
-  m_pPage = NULL;
-  m_bBufSpecified = FALSE;
-  m_pPause = pPause;
-  m_nSegmentDecoded = 0;
-  m_PauseStep = 10;
-  m_pArithDecoder = NULL;
-  m_pGRD = NULL;
-  m_gbContext = NULL;
-  m_dwOffset = 0;
-  m_ProcessiveStatus = FXCODEC_STATUS_FRAME_READY;
-  m_pSymbolDictCache = pSymbolDictCache;
+    m_pGlobalContext = nullptr;
+  }
+
+  m_pStream.reset(new CJBig2_BitStream(pData, dwLength));
 }
+
 CJBig2_Context::~CJBig2_Context() {
   delete m_pArithDecoder;
   m_pArithDecoder = NULL;
-  delete m_pGRD;
-  m_pGRD = NULL;
   FX_Free(m_gbContext);
   m_gbContext = NULL;
   delete m_pGlobalContext;
   m_pGlobalContext = NULL;
-  if (m_bBufSpecified) {
-    delete m_pPage;
-  }
-  m_pPage = NULL;
-  delete m_pStream;
-  m_pStream = NULL;
-}
-int32_t CJBig2_Context::decodeFile(IFX_Pause* pPause) {
-  uint8_t cFlags;
-  FX_DWORD dwTemp;
-  const uint8_t fileID[] = {0x97, 0x4A, 0x42, 0x32, 0x0D, 0x0A, 0x1A, 0x0A};
-  int32_t nRet;
-  if (m_pStream->getByteLeft() < 8) {
-    nRet = JBIG2_ERROR_TOO_SHORT;
-    goto failed;
-  }
-  if (JBIG2_memcmp(m_pStream->getPointer(), fileID, 8) != 0) {
-    nRet = JBIG2_ERROR_FILE_FORMAT;
-    goto failed;
-  }
-  m_pStream->offset(8);
-  if (m_pStream->read1Byte(&cFlags) != 0) {
-    nRet = JBIG2_ERROR_TOO_SHORT;
-    goto failed;
-  }
-  if (!(cFlags & 0x02)) {
-    if (m_pStream->readInteger(&dwTemp) != 0) {
-      nRet = JBIG2_ERROR_TOO_SHORT;
-      goto failed;
-    }
-    if (dwTemp > 0) {
-      m_PageInfoList.clear();
-      m_PageInfoList.resize(dwTemp);
-    }
-  }
-  if (cFlags & 0x01) {
-    m_nStreamType = JBIG2_SQUENTIAL_STREAM;
-    return decode_SquentialOrgnazation(pPause);
-  } else {
-    m_nStreamType = JBIG2_RANDOM_STREAM;
-    return decode_RandomOrgnazation_FirstPage(pPause);
-  }
-failed:
-  return nRet;
 }
+
 int32_t CJBig2_Context::decode_SquentialOrgnazation(IFX_Pause* pPause) {
   int32_t nRet;
   if (m_pStream->getByteLeft() <= 0)
@@ -129,8 +96,8 @@ int32_t CJBig2_Context::decode_SquentialOrgnazation(IFX_Pause* pPause) {
       m_dwOffset = m_pStream->getOffset();
     }
     nRet = parseSegmentData(m_pSegment.get(), pPause);
-    if (m_ProcessiveStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
-      m_ProcessiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
+    if (m_ProcessingStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
+      m_ProcessingStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
       m_PauseStep = 2;
       return JBIG2_SUCCESS;
     }
@@ -143,7 +110,7 @@ int32_t CJBig2_Context::decode_SquentialOrgnazation(IFX_Pause* pPause) {
       return nRet;
     }
     if (m_pSegment->m_dwData_length != 0xffffffff) {
-      m_dwOffset = m_dwOffset + m_pSegment->m_dwData_length;
+      m_dwOffset += m_pSegment->m_dwData_length;
       m_pStream->setOffset(m_dwOffset);
     } else {
       m_pStream->offset(4);
@@ -151,7 +118,7 @@ int32_t CJBig2_Context::decode_SquentialOrgnazation(IFX_Pause* pPause) {
     m_SegmentList.push_back(m_pSegment.release());
     if (m_pStream->getByteLeft() > 0 && m_pPage && pPause &&
         pPause->NeedToPauseNow()) {
-      m_ProcessiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
+      m_ProcessingStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
       m_PauseStep = 2;
       return JBIG2_SUCCESS;
     }
@@ -174,7 +141,7 @@ int32_t CJBig2_Context::decode_RandomOrgnazation_FirstPage(IFX_Pause* pPause) {
     m_SegmentList.push_back(pSegment.release());
     if (pPause && m_pPause && pPause->NeedToPauseNow()) {
       m_PauseStep = 3;
-      m_ProcessiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
+      m_ProcessingStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
       return JBIG2_SUCCESS;
     }
   }
@@ -193,7 +160,7 @@ int32_t CJBig2_Context::decode_RandomOrgnazation(IFX_Pause* pPause) {
 
     if (m_pPage && pPause && pPause->NeedToPauseNow()) {
       m_PauseStep = 4;
-      m_ProcessiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
+      m_ProcessingStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
       return JBIG2_SUCCESS;
     }
   }
@@ -208,48 +175,25 @@ int32_t CJBig2_Context::getFirstPage(uint8_t* pBuf,
   if (m_pGlobalContext) {
     nRet = m_pGlobalContext->decode_EmbedOrgnazation(pPause);
     if (nRet != JBIG2_SUCCESS) {
-      m_ProcessiveStatus = FXCODEC_STATUS_ERROR;
+      m_ProcessingStatus = FXCODEC_STATUS_ERROR;
       return nRet;
     }
   }
-  m_bFirstPage = TRUE;
   m_PauseStep = 0;
-  delete m_pPage;
-  m_pPage = new CJBig2_Image(width, height, stride, pBuf);
-  m_bBufSpecified = TRUE;
-  if (m_pPage && pPause && pPause->NeedToPauseNow()) {
+  m_pPage.reset(new CJBig2_Image(width, height, stride, pBuf));
+  m_bBufSpecified = true;
+  if (pPause && pPause->NeedToPauseNow()) {
     m_PauseStep = 1;
-    m_ProcessiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
+    m_ProcessingStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
     return nRet;
   }
-  int ret = Continue(pPause);
-  return ret;
+  return Continue(pPause);
 }
 int32_t CJBig2_Context::Continue(IFX_Pause* pPause) {
-  m_ProcessiveStatus = FXCODEC_STATUS_DECODE_READY;
+  m_ProcessingStatus = FXCODEC_STATUS_DECODE_READY;
   int32_t nRet;
   if (m_PauseStep <= 1) {
-    switch (m_nStreamType) {
-      case JBIG2_FILE_STREAM:
-        nRet = decodeFile(pPause);
-        break;
-      case JBIG2_SQUENTIAL_STREAM:
-        nRet = decode_SquentialOrgnazation(pPause);
-        break;
-      case JBIG2_RANDOM_STREAM:
-        if (m_bFirstPage) {
-          nRet = decode_RandomOrgnazation_FirstPage(pPause);
-        } else {
-          nRet = decode_RandomOrgnazation(pPause);
-        }
-        break;
-      case JBIG2_EMBED_STREAM:
-        nRet = decode_EmbedOrgnazation(pPause);
-        break;
-      default:
-        m_ProcessiveStatus = FXCODEC_STATUS_ERROR;
-        return JBIG2_ERROR_STREAM_TYPE;
-    }
+    nRet = decode_EmbedOrgnazation(pPause);
   } else if (m_PauseStep == 2) {
     nRet = decode_SquentialOrgnazation(pPause);
   } else if (m_PauseStep == 3) {
@@ -257,37 +201,25 @@ int32_t CJBig2_Context::Continue(IFX_Pause* pPause) {
   } else if (m_PauseStep == 4) {
     nRet = decode_RandomOrgnazation(pPause);
   } else if (m_PauseStep == 5) {
-    m_ProcessiveStatus = FXCODEC_STATUS_DECODE_FINISH;
+    m_ProcessingStatus = FXCODEC_STATUS_DECODE_FINISH;
     return JBIG2_SUCCESS;
   }
-  if (m_ProcessiveStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
+  if (m_ProcessingStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
     return nRet;
   }
   m_PauseStep = 5;
   if (!m_bBufSpecified && nRet == JBIG2_SUCCESS) {
-    m_ProcessiveStatus = FXCODEC_STATUS_DECODE_FINISH;
+    m_ProcessingStatus = FXCODEC_STATUS_DECODE_FINISH;
     return JBIG2_SUCCESS;
   }
   if (nRet == JBIG2_SUCCESS) {
-    m_ProcessiveStatus = FXCODEC_STATUS_DECODE_FINISH;
+    m_ProcessingStatus = FXCODEC_STATUS_DECODE_FINISH;
   } else {
-    m_ProcessiveStatus = FXCODEC_STATUS_ERROR;
+    m_ProcessingStatus = FXCODEC_STATUS_ERROR;
   }
   return nRet;
 }
-int32_t CJBig2_Context::getFirstPage(CJBig2_Image** image, IFX_Pause* pPause) {
-  int32_t nRet;
-  m_bFirstPage = TRUE;
-  m_PauseStep = 0;
-  if (m_pGlobalContext) {
-    nRet = m_pGlobalContext->decode_EmbedOrgnazation(pPause);
-    if (nRet != JBIG2_SUCCESS) {
-      return nRet;
-    }
-  }
-  m_bBufSpecified = FALSE;
-  return Continue(pPause);
-}
+
 CJBig2_Segment* CJBig2_Context::findSegmentByNumber(FX_DWORD dwNumber) {
   CJBig2_Segment* pSeg;
   if (m_pGlobalContext) {
@@ -324,19 +256,17 @@ CJBig2_Segment* CJBig2_Context::findReferredSegmentByTypeAndIndex(
   return NULL;
 }
 int32_t CJBig2_Context::parseSegmentHeader(CJBig2_Segment* pSegment) {
-  uint8_t cSSize, cPSize;
-  uint8_t cTemp;
-  FX_WORD wTemp;
-  FX_DWORD dwTemp;
   if ((m_pStream->readInteger(&pSegment->m_dwNumber) != 0) ||
       (m_pStream->read1Byte(&pSegment->m_cFlags.c) != 0)) {
-    goto failed;
+    return JBIG2_ERROR_TOO_SHORT;
   }
-  cTemp = m_pStream->getCurByte();
+
+  FX_DWORD dwTemp;
+  uint8_t cTemp = m_pStream->getCurByte();
   if ((cTemp >> 5) == 7) {
     if (m_pStream->readInteger(
             (FX_DWORD*)&pSegment->m_nReferred_to_segment_count) != 0) {
-      goto failed;
+      return JBIG2_ERROR_TOO_SHORT;
     }
     pSegment->m_nReferred_to_segment_count &= 0x1fffffff;
     if (pSegment->m_nReferred_to_segment_count >
@@ -345,75 +275,72 @@ int32_t CJBig2_Context::parseSegmentHeader(CJBig2_Segment* pSegment) {
     }
     dwTemp = 5 + 4 + (pSegment->m_nReferred_to_segment_count + 1) / 8;
   } else {
-    if (m_pStream->read1Byte(&cTemp) != 0) {
-      goto failed;
-    }
+    if (m_pStream->read1Byte(&cTemp) != 0)
+      return JBIG2_ERROR_TOO_SHORT;
+
     pSegment->m_nReferred_to_segment_count = cTemp >> 5;
     dwTemp = 5 + 1;
   }
-  cSSize =
+  uint8_t cSSize =
       pSegment->m_dwNumber > 65536 ? 4 : pSegment->m_dwNumber > 256 ? 2 : 1;
-  cPSize = pSegment->m_cFlags.s.page_association_size ? 4 : 1;
+  uint8_t cPSize = pSegment->m_cFlags.s.page_association_size ? 4 : 1;
   if (pSegment->m_nReferred_to_segment_count) {
     pSegment->m_pReferred_to_segment_numbers =
         FX_Alloc(FX_DWORD, pSegment->m_nReferred_to_segment_count);
     for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; i++) {
       switch (cSSize) {
         case 1:
-          if (m_pStream->read1Byte(&cTemp) != 0) {
-            goto failed;
-          }
+          if (m_pStream->read1Byte(&cTemp) != 0)
+            return JBIG2_ERROR_TOO_SHORT;
+
           pSegment->m_pReferred_to_segment_numbers[i] = cTemp;
           break;
         case 2:
-          if (m_pStream->readShortInteger(&wTemp) != 0) {
-            goto failed;
-          }
+          FX_WORD wTemp;
+          if (m_pStream->readShortInteger(&wTemp) != 0)
+            return JBIG2_ERROR_TOO_SHORT;
+
           pSegment->m_pReferred_to_segment_numbers[i] = wTemp;
           break;
         case 4:
-          if (m_pStream->readInteger(&dwTemp) != 0) {
-            goto failed;
-          }
+          if (m_pStream->readInteger(&dwTemp) != 0)
+            return JBIG2_ERROR_TOO_SHORT;
+
           pSegment->m_pReferred_to_segment_numbers[i] = dwTemp;
           break;
       }
-      if (pSegment->m_pReferred_to_segment_numbers[i] >= pSegment->m_dwNumber) {
-        goto failed;
-      }
+      if (pSegment->m_pReferred_to_segment_numbers[i] >= pSegment->m_dwNumber)
+        return JBIG2_ERROR_TOO_SHORT;
     }
   }
   if (cPSize == 1) {
-    if (m_pStream->read1Byte(&cTemp) != 0) {
-      goto failed;
-    }
+    if (m_pStream->read1Byte(&cTemp) != 0)
+      return JBIG2_ERROR_TOO_SHORT;
     pSegment->m_dwPage_association = cTemp;
   } else {
     if (m_pStream->readInteger(&pSegment->m_dwPage_association) != 0) {
-      goto failed;
+      return JBIG2_ERROR_TOO_SHORT;
     }
   }
-  if (m_pStream->readInteger(&pSegment->m_dwData_length) != 0) {
-    goto failed;
-  }
+  if (m_pStream->readInteger(&pSegment->m_dwData_length) != 0)
+    return JBIG2_ERROR_TOO_SHORT;
+
   pSegment->m_pData = m_pStream->getPointer();
   pSegment->m_State = JBIG2_SEGMENT_DATA_UNPARSED;
   return JBIG2_SUCCESS;
-failed:
-  return JBIG2_ERROR_TOO_SHORT;
 }
 
 int32_t CJBig2_Context::parseSegmentData(CJBig2_Segment* pSegment,
                                          IFX_Pause* pPause) {
-  int32_t ret = ProcessiveParseSegmentData(pSegment, pPause);
-  while (m_ProcessiveStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE &&
+  int32_t ret = ProcessingParseSegmentData(pSegment, pPause);
+  while (m_ProcessingStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE &&
          m_pStream->getByteLeft() > 0) {
-    ret = ProcessiveParseSegmentData(pSegment, pPause);
+    ret = ProcessingParseSegmentData(pSegment, pPause);
   }
   return ret;
 }
 
-int32_t CJBig2_Context::ProcessiveParseSegmentData(CJBig2_Segment* pSegment,
+int32_t CJBig2_Context::ProcessingParseSegmentData(CJBig2_Segment* pSegment,
                                                    IFX_Pause* pPause) {
   switch (pSegment->m_cFlags.s.type) {
     case 0:
@@ -421,7 +348,7 @@ int32_t CJBig2_Context::ProcessiveParseSegmentData(CJBig2_Segment* pSegment,
     case 4:
     case 6:
     case 7:
-      if (m_nState == JBIG2_OUT_OF_PAGE)
+      if (!m_bInPage)
         return JBIG2_ERROR_FATAL;
       return parseTextRegion(pSegment);
     case 16:
@@ -429,19 +356,19 @@ int32_t CJBig2_Context::ProcessiveParseSegmentData(CJBig2_Segment* pSegment,
     case 20:
     case 22:
     case 23:
-      if (m_nState == JBIG2_OUT_OF_PAGE)
+      if (!m_bInPage)
         return JBIG2_ERROR_FATAL;
       return parseHalftoneRegion(pSegment, pPause);
     case 36:
     case 38:
     case 39:
-      if (m_nState == JBIG2_OUT_OF_PAGE)
+      if (!m_bInPage)
         return JBIG2_ERROR_FATAL;
       return parseGenericRegion(pSegment, pPause);
     case 40:
     case 42:
     case 43:
-      if (m_nState == JBIG2_OUT_OF_PAGE)
+      if (!m_bInPage)
         return JBIG2_ERROR_FATAL;
       return parseGenericRefinementRegion(pSegment);
     case 48: {
@@ -462,23 +389,22 @@ int32_t CJBig2_Context::ProcessiveParseSegmentData(CJBig2_Segment* pSegment,
         pPageInfo->m_bIsStriped = TRUE;
 
       if (!m_bBufSpecified) {
-        delete m_pPage;
         FX_DWORD height =
             bMaxHeight ? pPageInfo->m_wMaxStripeSize : pPageInfo->m_dwHeight;
-        m_pPage = new CJBig2_Image(pPageInfo->m_dwWidth, height);
+        m_pPage.reset(new CJBig2_Image(pPageInfo->m_dwWidth, height));
       }
 
       if (!m_pPage->m_pData) {
-        m_ProcessiveStatus = FXCODEC_STATUS_ERROR;
+        m_ProcessingStatus = FXCODEC_STATUS_ERROR;
         return JBIG2_ERROR_TOO_SHORT;
       }
 
       m_pPage->fill((pPageInfo->m_cFlags & 4) ? 1 : 0);
       m_PageInfoList.push_back(pPageInfo.release());
-      m_nState = JBIG2_IN_PAGE;
+      m_bInPage = true;
     } break;
     case 49:
-      m_nState = JBIG2_OUT_OF_PAGE;
+      m_bInPage = false;
       return JBIG2_END_OF_PAGE;
       break;
     case 50:
@@ -505,13 +431,18 @@ int32_t CJBig2_Context::parseSymbolDict(CJBig2_Segment* pSegment,
   FX_DWORD dwTemp;
   FX_WORD wFlags;
   uint8_t cSDHUFFDH, cSDHUFFDW, cSDHUFFBMSIZE, cSDHUFFAGGINST;
-  CJBig2_HuffmanTable *Table_B1 = NULL, *Table_B2 = NULL, *Table_B3 = NULL,
-                      *Table_B4 = NULL, *Table_B5 = NULL;
+  CJBig2_HuffmanTable* Table_B1 = nullptr;
+  CJBig2_HuffmanTable* Table_B2 = nullptr;
+  CJBig2_HuffmanTable* Table_B3 = nullptr;
+  CJBig2_HuffmanTable* Table_B4 = nullptr;
+  CJBig2_HuffmanTable* Table_B5 = nullptr;
   int32_t i, nIndex, nRet;
-  CJBig2_Segment *pSeg = NULL, *pLRSeg = NULL;
+  CJBig2_Segment* pSeg = nullptr;
+  CJBig2_Segment* pLRSeg = nullptr;
   FX_BOOL bUsed;
-  CJBig2_Image** SDINSYMS = NULL;
-  JBig2ArithCtx *gbContext = NULL, *grContext = NULL;
+  CJBig2_Image** SDINSYMS = nullptr;
+  JBig2ArithCtx* gbContext = nullptr;
+  JBig2ArithCtx* grContext = nullptr;
   CJBig2_ArithDecoder* pArithDecoder;
   CJBig2_SDDProc* pSymbolDictDecoder = new CJBig2_SDDProc();
   const uint8_t* key = pSegment->m_pData;
@@ -695,7 +626,8 @@ int32_t CJBig2_Context::parseSymbolDict(CJBig2_Segment* pSegment,
   for (std::list<CJBig2_CachePair>::iterator it = m_pSymbolDictCache->begin();
        it != m_pSymbolDictCache->end(); ++it) {
     if (it->first == key) {
-      pSegment->m_Result.sd = it->second->DeepCopy();
+      nonstd::unique_ptr<CJBig2_SymbolDict> copy(it->second->DeepCopy());
+      pSegment->m_Result.sd = copy.release();
       m_pSymbolDictCache->push_front(*it);
       m_pSymbolDictCache->erase(it);
       cache_hit = true;
@@ -704,7 +636,7 @@ int32_t CJBig2_Context::parseSymbolDict(CJBig2_Segment* pSegment,
   }
   if (!cache_hit) {
     if (pSymbolDictDecoder->SDHUFF == 0) {
-      pArithDecoder = new CJBig2_ArithDecoder(m_pStream);
+      pArithDecoder = new CJBig2_ArithDecoder(m_pStream.get());
       pSegment->m_Result.sd =
           pSymbolDictDecoder->decode_Arith(pArithDecoder, gbContext, grContext);
       delete pArithDecoder;
@@ -716,21 +648,24 @@ int32_t CJBig2_Context::parseSymbolDict(CJBig2_Segment* pSegment,
       m_pStream->offset(2);
     } else {
       pSegment->m_Result.sd = pSymbolDictDecoder->decode_Huffman(
-          m_pStream, gbContext, grContext, pPause);
+          m_pStream.get(), gbContext, grContext, pPause);
       if (pSegment->m_Result.sd == NULL) {
         nRet = JBIG2_ERROR_FATAL;
         goto failed;
       }
       m_pStream->alignByte();
     }
-    CJBig2_SymbolDict* value = pSegment->m_Result.sd->DeepCopy();
+#ifndef DISABLE_SYMBOL_CACHE
+    nonstd::unique_ptr<CJBig2_SymbolDict> value =
+        pSegment->m_Result.sd->DeepCopy();
     if (value && kSymbolDictCacheMaxSize > 0) {
       while (m_pSymbolDictCache->size() >= kSymbolDictCacheMaxSize) {
         delete m_pSymbolDictCache->back().second;
         m_pSymbolDictCache->pop_back();
       }
-      m_pSymbolDictCache->push_front(CJBig2_CachePair(key, value));
+      m_pSymbolDictCache->push_front(CJBig2_CachePair(key, value.release()));
     }
+#endif
   }
   if (wFlags & 0x0200) {
     pSegment->m_Result.sd->m_bContextRetained = TRUE;
@@ -775,15 +710,22 @@ int32_t CJBig2_Context::parseTextRegion(CJBig2_Segment* pSegment) {
   int32_t i, nIndex, nRet;
   JBig2RegionInfo ri;
   CJBig2_Segment* pSeg;
-  CJBig2_Image** SBSYMS = NULL;
-  JBig2HuffmanCode* SBSYMCODES = NULL;
+  CJBig2_Image** SBSYMS = nullptr;
+  JBig2HuffmanCode* SBSYMCODES = nullptr;
   uint8_t cSBHUFFFS, cSBHUFFDS, cSBHUFFDT, cSBHUFFRDW, cSBHUFFRDH, cSBHUFFRDX,
       cSBHUFFRDY, cSBHUFFRSIZE;
-  CJBig2_HuffmanTable *Table_B1 = NULL, *Table_B6 = NULL, *Table_B7 = NULL,
-                      *Table_B8 = NULL, *Table_B9 = NULL, *Table_B10 = NULL,
-                      *Table_B11 = NULL, *Table_B12 = NULL, *Table_B13 = NULL,
-                      *Table_B14 = NULL, *Table_B15 = NULL;
-  JBig2ArithCtx* grContext = NULL;
+  CJBig2_HuffmanTable* Table_B1 = nullptr;
+  CJBig2_HuffmanTable* Table_B6 = nullptr;
+  CJBig2_HuffmanTable* Table_B7 = nullptr;
+  CJBig2_HuffmanTable* Table_B8 = nullptr;
+  CJBig2_HuffmanTable* Table_B9 = nullptr;
+  CJBig2_HuffmanTable* Table_B10 = nullptr;
+  CJBig2_HuffmanTable* Table_B11 = nullptr;
+  CJBig2_HuffmanTable* Table_B12 = nullptr;
+  CJBig2_HuffmanTable* Table_B13 = nullptr;
+  CJBig2_HuffmanTable* Table_B14 = nullptr;
+  CJBig2_HuffmanTable* Table_B15 = nullptr;
+  JBig2ArithCtx* grContext = nullptr;
   CJBig2_ArithDecoder* pArithDecoder;
   CJBig2_TRDProc* pTRD = new CJBig2_TRDProc();
   if ((parseRegionInfo(&ri) != JBIG2_SUCCESS) ||
@@ -861,7 +803,7 @@ int32_t CJBig2_Context::parseTextRegion(CJBig2_Segment* pSegment) {
     pTRD->SBSYMS = NULL;
   }
   if (pTRD->SBHUFF == 1) {
-    SBSYMCODES = decodeSymbolIDHuffmanTable(m_pStream, pTRD->SBNUMSYMS);
+    SBSYMCODES = decodeSymbolIDHuffmanTable(m_pStream.get(), pTRD->SBNUMSYMS);
     if (SBSYMCODES == NULL) {
       nRet = JBIG2_ERROR_FATAL;
       goto failed;
@@ -1050,7 +992,7 @@ int32_t CJBig2_Context::parseTextRegion(CJBig2_Segment* pSegment) {
     JBIG2_memset(grContext, 0, sizeof(JBig2ArithCtx) * dwTemp);
   }
   if (pTRD->SBHUFF == 0) {
-    pArithDecoder = new CJBig2_ArithDecoder(m_pStream);
+    pArithDecoder = new CJBig2_ArithDecoder(m_pStream.get());
     pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
     pSegment->m_Result.im = pTRD->decode_Arith(pArithDecoder, grContext);
     delete pArithDecoder;
@@ -1062,7 +1004,7 @@ int32_t CJBig2_Context::parseTextRegion(CJBig2_Segment* pSegment) {
     m_pStream->offset(2);
   } else {
     pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
-    pSegment->m_Result.im = pTRD->decode_Huffman(m_pStream, grContext);
+    pSegment->m_Result.im = pTRD->decode_Huffman(m_pStream.get(), grContext);
     if (pSegment->m_Result.im == NULL) {
       nRet = JBIG2_ERROR_FATAL;
       goto failed;
@@ -1144,7 +1086,7 @@ int32_t CJBig2_Context::parsePatternDict(CJBig2_Segment* pSegment,
         pPDD->HDTEMPLATE == 0 ? 65536 : pPDD->HDTEMPLATE == 1 ? 8192 : 1024;
     gbContext = FX_Alloc(JBig2ArithCtx, dwTemp);
     JBIG2_memset(gbContext, 0, sizeof(JBig2ArithCtx) * dwTemp);
-    pArithDecoder = new CJBig2_ArithDecoder(m_pStream);
+    pArithDecoder = new CJBig2_ArithDecoder(m_pStream.get());
     pSegment->m_Result.pd =
         pPDD->decode_Arith(pArithDecoder, gbContext, pPause);
     delete pArithDecoder;
@@ -1157,7 +1099,7 @@ int32_t CJBig2_Context::parsePatternDict(CJBig2_Segment* pSegment,
     m_pStream->alignByte();
     m_pStream->offset(2);
   } else {
-    pSegment->m_Result.pd = pPDD->decode_MMR(m_pStream, pPause);
+    pSegment->m_Result.pd = pPDD->decode_MMR(m_pStream.get(), pPause);
     if (pSegment->m_Result.pd == NULL) {
       nRet = JBIG2_ERROR_FATAL;
       goto failed;
@@ -1192,6 +1134,11 @@ int32_t CJBig2_Context::parseHalftoneRegion(CJBig2_Segment* pSegment,
     nRet = JBIG2_ERROR_TOO_SHORT;
     goto failed;
   }
+  if (pHRD->HGW == 0 || pHRD->HGH == 0) {
+    nRet = JBIG2_ERROR_FATAL;
+    goto failed;
+  }
+
   pHRD->HBW = ri.width;
   pHRD->HBH = ri.height;
   pHRD->HMMR = cFlags & 0x01;
@@ -1222,7 +1169,7 @@ int32_t CJBig2_Context::parseHalftoneRegion(CJBig2_Segment* pSegment,
     dwTemp = pHRD->HTEMPLATE == 0 ? 65536 : pHRD->HTEMPLATE == 1 ? 8192 : 1024;
     gbContext = FX_Alloc(JBig2ArithCtx, dwTemp);
     JBIG2_memset(gbContext, 0, sizeof(JBig2ArithCtx) * dwTemp);
-    pArithDecoder = new CJBig2_ArithDecoder(m_pStream);
+    pArithDecoder = new CJBig2_ArithDecoder(m_pStream.get());
     pSegment->m_Result.im =
         pHRD->decode_Arith(pArithDecoder, gbContext, pPause);
     delete pArithDecoder;
@@ -1235,7 +1182,7 @@ int32_t CJBig2_Context::parseHalftoneRegion(CJBig2_Segment* pSegment,
     m_pStream->alignByte();
     m_pStream->offset(2);
   } else {
-    pSegment->m_Result.im = pHRD->decode_MMR(m_pStream, pPause);
+    pSegment->m_Result.im = pHRD->decode_MMR(m_pStream.get(), pPause);
     if (pSegment->m_Result.im == NULL) {
       nRet = JBIG2_ERROR_FATAL;
       goto failed;
@@ -1267,8 +1214,8 @@ int32_t CJBig2_Context::parseGenericRegion(CJBig2_Segment* pSegment,
   FX_DWORD dwTemp;
   uint8_t cFlags;
   int32_t i, nRet;
-  if (m_pGRD == NULL) {
-    m_pGRD = new CJBig2_GRDProc();
+  if (!m_pGRD) {
+    m_pGRD.reset(new CJBig2_GRDProc);
     if ((parseRegionInfo(&m_ri) != JBIG2_SUCCESS) ||
         (m_pStream->read1Byte(&cFlags) != 0)) {
       nRet = JBIG2_ERROR_TOO_SHORT;
@@ -1311,13 +1258,13 @@ int32_t CJBig2_Context::parseGenericRegion(CJBig2_Segment* pSegment,
       JBIG2_memset(m_gbContext, 0, sizeof(JBig2ArithCtx) * dwTemp);
     }
     if (m_pArithDecoder == NULL) {
-      m_pArithDecoder = new CJBig2_ArithDecoder(m_pStream);
-      m_ProcessiveStatus = m_pGRD->Start_decode_Arith(
+      m_pArithDecoder = new CJBig2_ArithDecoder(m_pStream.get());
+      m_ProcessingStatus = m_pGRD->Start_decode_Arith(
           &pSegment->m_Result.im, m_pArithDecoder, m_gbContext, pPause);
     } else {
-      m_ProcessiveStatus = m_pGRD->Continue_decode(pPause);
+      m_ProcessingStatus = m_pGRD->Continue_decode(pPause);
     }
-    if (m_ProcessiveStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
+    if (m_ProcessingStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
       if (pSegment->m_cFlags.s.type != 36) {
         if (!m_bBufSpecified) {
           JBig2PageInfo* pPageInfo = m_PageInfoList.back();
@@ -1340,7 +1287,7 @@ int32_t CJBig2_Context::parseGenericRegion(CJBig2_Segment* pSegment,
         FX_Free(m_gbContext);
         nRet = JBIG2_ERROR_FATAL;
         m_gbContext = NULL;
-        m_ProcessiveStatus = FXCODEC_STATUS_ERROR;
+        m_ProcessingStatus = FXCODEC_STATUS_ERROR;
         goto failed;
       }
       FX_Free(m_gbContext);
@@ -1349,8 +1296,8 @@ int32_t CJBig2_Context::parseGenericRegion(CJBig2_Segment* pSegment,
       m_pStream->offset(2);
     }
   } else {
-    FXCODEC_STATUS status =
-        m_pGRD->Start_decode_MMR(&pSegment->m_Result.im, m_pStream, pPause);
+    FXCODEC_STATUS status = m_pGRD->Start_decode_MMR(&pSegment->m_Result.im,
+                                                     m_pStream.get(), pPause);
     while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
       m_pGRD->Continue_decode(pPause);
     }
@@ -1376,12 +1323,10 @@ int32_t CJBig2_Context::parseGenericRegion(CJBig2_Segment* pSegment,
     delete pSegment->m_Result.im;
     pSegment->m_Result.im = NULL;
   }
-  delete m_pGRD;
-  m_pGRD = NULL;
+  m_pGRD.reset();
   return JBIG2_SUCCESS;
 failed:
-  delete m_pGRD;
-  m_pGRD = NULL;
+  m_pGRD.reset();
   return nRet;
 }
 
@@ -1430,14 +1375,14 @@ int32_t CJBig2_Context::parseGenericRefinementRegion(CJBig2_Segment* pSegment) {
     }
     pGRRD->GRREFERENCE = pSeg->m_Result.im;
   } else {
-    pGRRD->GRREFERENCE = m_pPage;
+    pGRRD->GRREFERENCE = m_pPage.get();
   }
   pGRRD->GRREFERENCEDX = 0;
   pGRRD->GRREFERENCEDY = 0;
   dwTemp = pGRRD->GRTEMPLATE ? 1 << 10 : 1 << 13;
   grContext = FX_Alloc(JBig2ArithCtx, dwTemp);
   JBIG2_memset(grContext, 0, sizeof(JBig2ArithCtx) * dwTemp);
-  pArithDecoder = new CJBig2_ArithDecoder(m_pStream);
+  pArithDecoder = new CJBig2_ArithDecoder(m_pStream.get());
   pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
   pSegment->m_Result.im = pGRRD->decode(pArithDecoder, grContext);
   delete pArithDecoder;
@@ -1470,7 +1415,7 @@ failed:
 }
 int32_t CJBig2_Context::parseTable(CJBig2_Segment* pSegment) {
   pSegment->m_nResultType = JBIG2_HUFFMAN_TABLE_POINTER;
-  pSegment->m_Result.ht = new CJBig2_HuffmanTable(m_pStream);
+  pSegment->m_Result.ht = new CJBig2_HuffmanTable(m_pStream.get());
   if (!pSegment->m_Result.ht->isOK()) {
     delete pSegment->m_Result.ht;
     pSegment->m_Result.ht = NULL;