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); }
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)); }