Пример #1
0
CPDF_Stream* CPDF_StreamParser::ReadInlineStream(CPDF_Document* pDoc, CPDF_Dictionary* pDict, CPDF_Object* pCSObj, FX_BOOL bDecode)
{
    if (m_Pos == m_Size) {
        return NULL;
    }
    if (PDF_CharType[m_pBuf[m_Pos]] == 'W') {
        m_Pos ++;
    }
    CFX_ByteString Decoder;
    CPDF_Dictionary* pParam = NULL;
    CPDF_Object* pFilter = pDict->GetElementValue(FX_BSTRC("Filter"));
    if (pFilter == NULL) {
    } else if (pFilter->GetType() == PDFOBJ_ARRAY) {
        Decoder = ((CPDF_Array*)pFilter)->GetString(0);
        CPDF_Array* pParams = pDict->GetArray(FX_BSTRC("DecodeParms"));
        if (pParams) {
            pParam = pParams->GetDict(0);
        }
    } else {
        Decoder = pFilter->GetString();
        pParam = pDict->GetDict(FX_BSTRC("DecodeParms"));
    }
    FX_DWORD width = pDict->GetInteger(FX_BSTRC("Width"));
    FX_DWORD height = pDict->GetInteger(FX_BSTRC("Height"));
    FX_DWORD OrigSize = 0;
    if (pCSObj != NULL) {
        FX_DWORD bpc = pDict->GetInteger(FX_BSTRC("BitsPerComponent"));
        FX_DWORD nComponents = 1;
        CPDF_ColorSpace* pCS = pDoc->LoadColorSpace(pCSObj);
        if (pCS == NULL) {
            nComponents = 3;
        } else {
            nComponents = pCS->CountComponents();
            pDoc->GetPageData()->ReleaseColorSpace(pCSObj);
        }
        FX_DWORD pitch = width;
        if (bpc && pitch > INT_MAX / bpc) {
            return NULL;
        }
        pitch *= bpc;
        if (nComponents && pitch > INT_MAX / nComponents) {
            return NULL;
        }
        pitch *= nComponents;
        if (pitch > INT_MAX - 7) {
            return NULL;
        }
        pitch += 7;
        pitch /= 8;
        OrigSize = pitch;
    } else {
        if (width > INT_MAX - 7) {
            return NULL;
        }
        OrigSize = ((width + 7) / 8);
    }
    if (height && OrigSize > INT_MAX / height) {
        return NULL;
    }
    OrigSize *= height;
    uint8_t* pData = NULL;
    FX_DWORD dwStreamSize;
    if (Decoder.IsEmpty()) {
        if (OrigSize > m_Size - m_Pos) {
            OrigSize = m_Size - m_Pos;
        }
        pData = FX_Alloc(uint8_t, OrigSize);
        FXSYS_memcpy(pData, m_pBuf + m_Pos, OrigSize);
        dwStreamSize = OrigSize;
        m_Pos += OrigSize;
    } else {
        FX_DWORD dwDestSize = OrigSize;
        dwStreamSize = PDF_DecodeInlineStream(m_pBuf + m_Pos, m_Size - m_Pos, width, height, Decoder, pParam,
                                              pData, dwDestSize);
        if ((int)dwStreamSize < 0) {
            return NULL;
        }
        if (bDecode) {
            m_Pos += dwStreamSize;
            dwStreamSize = dwDestSize;
            if (pFilter->GetType() == PDFOBJ_ARRAY) {
                ((CPDF_Array*)pFilter)->RemoveAt(0);
                CPDF_Array* pParams = pDict->GetArray(FX_BSTRC("DecodeParms"));
                if (pParams) {
                    pParams->RemoveAt(0);
                }
            } else {
                pDict->RemoveAt(FX_BSTRC("Filter"));
                pDict->RemoveAt(FX_BSTRC("DecodeParms"));
            }
        } else {
            if (pData) {
                FX_Free(pData);
            }
            FX_DWORD dwSavePos = m_Pos;
            m_Pos += dwStreamSize;
            while (1) {
                FX_DWORD dwPrevPos = m_Pos;
                CPDF_StreamParser::SyntaxType type = ParseNextElement();
                if (type == CPDF_StreamParser::EndOfData) {
                    break;
                }
                if (type != CPDF_StreamParser::Keyword) {
                    dwStreamSize += m_Pos - dwPrevPos;
                    continue;
                }
                if (GetWordSize() == 2 && GetWordBuf()[0] == 'E' &&
                        GetWordBuf()[1] == 'I') {
                    m_Pos = dwPrevPos;
                    break;
                }
                dwStreamSize += m_Pos - dwPrevPos;
            }
            m_Pos = dwSavePos;
            pData = FX_Alloc(uint8_t, dwStreamSize);
            FXSYS_memcpy(pData, m_pBuf + m_Pos, dwStreamSize);
            m_Pos += dwStreamSize;
        }
    }
    pDict->SetAtInteger(FX_BSTRC("Length"), (int)dwStreamSize);
    return CPDF_Stream::Create(pData, dwStreamSize, pDict);
}
Пример #2
0
std::unique_ptr<CPDF_Stream> CPDF_StreamParser::ReadInlineStream(
    CPDF_Document* pDoc,
    std::unique_ptr<CPDF_Dictionary> pDict,
    const CPDF_Object* pCSObj) {
  if (m_Pos < m_pBuf.size() && PDFCharIsWhitespace(m_pBuf[m_Pos]))
    m_Pos++;

  if (m_Pos == m_pBuf.size())
    return nullptr;

  ByteString Decoder;
  CPDF_Dictionary* pParam = nullptr;
  CPDF_Object* pFilter = pDict->GetDirectObjectFor("Filter");
  if (pFilter) {
    if (CPDF_Array* pArray = pFilter->AsArray()) {
      Decoder = pArray->GetStringAt(0);
      CPDF_Array* pParams = pDict->GetArrayFor(pdfium::stream::kDecodeParms);
      if (pParams)
        pParam = pParams->GetDictAt(0);
    } else {
      Decoder = pFilter->GetString();
      pParam = pDict->GetDictFor(pdfium::stream::kDecodeParms);
    }
  }
  uint32_t width = pDict->GetIntegerFor("Width");
  uint32_t height = pDict->GetIntegerFor("Height");
  uint32_t OrigSize = 0;
  if (pCSObj) {
    uint32_t bpc = pDict->GetIntegerFor("BitsPerComponent");
    uint32_t nComponents = 1;
    CPDF_ColorSpace* pCS = pDoc->LoadColorSpace(pCSObj, nullptr);
    if (pCS) {
      nComponents = pCS->CountComponents();
      pDoc->GetPageData()->ReleaseColorSpace(pCSObj);
    } else {
      nComponents = 3;
    }
    uint32_t pitch = width;
    if (bpc && pitch > INT_MAX / bpc)
      return nullptr;

    pitch *= bpc;
    if (nComponents && pitch > INT_MAX / nComponents)
      return nullptr;

    pitch *= nComponents;
    if (pitch > INT_MAX - 7)
      return nullptr;

    pitch += 7;
    pitch /= 8;
    OrigSize = pitch;
  } else {
    if (width > INT_MAX - 7)
      return nullptr;

    OrigSize = ((width + 7) / 8);
  }
  if (height && OrigSize > INT_MAX / height)
    return nullptr;

  OrigSize *= height;
  std::unique_ptr<uint8_t, FxFreeDeleter> pData;
  uint32_t dwStreamSize;
  if (Decoder.IsEmpty()) {
    if (OrigSize > m_pBuf.size() - m_Pos)
      OrigSize = m_pBuf.size() - m_Pos;
    pData.reset(FX_Alloc(uint8_t, OrigSize));
    auto copy_span = m_pBuf.subspan(m_Pos, OrigSize);
    memcpy(pData.get(), copy_span.data(), copy_span.size());
    dwStreamSize = OrigSize;
    m_Pos += OrigSize;
  } else {
    dwStreamSize = DecodeInlineStream(m_pBuf.subspan(m_Pos), width, height,
                                      Decoder, pParam, OrigSize);
    if (static_cast<int>(dwStreamSize) < 0)
      return nullptr;

    uint32_t dwSavePos = m_Pos;
    m_Pos += dwStreamSize;
    while (1) {
      uint32_t dwPrevPos = m_Pos;
      CPDF_StreamParser::SyntaxType type = ParseNextElement();
      if (type == CPDF_StreamParser::EndOfData)
        break;

      if (type != CPDF_StreamParser::Keyword) {
        dwStreamSize += m_Pos - dwPrevPos;
        continue;
      }
      if (GetWord() == "EI") {
        m_Pos = dwPrevPos;
        break;
      }
      dwStreamSize += m_Pos - dwPrevPos;
    }
    m_Pos = dwSavePos;
    pData.reset(FX_Alloc(uint8_t, dwStreamSize));
    auto copy_span = m_pBuf.subspan(m_Pos, dwStreamSize);
    memcpy(pData.get(), copy_span.data(), copy_span.size());
    m_Pos += dwStreamSize;
  }
  pDict->SetNewFor<CPDF_Number>("Length", static_cast<int>(dwStreamSize));
  return pdfium::MakeUnique<CPDF_Stream>(std::move(pData), dwStreamSize,
                                         std::move(pDict));
}