CPDF_StructElement::CPDF_StructElement(CPDF_StructTree* pTree, CPDF_StructElement* pParent, const CPDF_Dictionary* pDict) : m_pTree(pTree), m_pParent(pParent), m_pDict(pDict), m_Type(pDict->GetStringFor("S")), m_Title(pDict->GetStringFor("T")) { if (pTree->GetRoleMap()) { ByteString mapped = pTree->GetRoleMap()->GetStringFor(m_Type); if (!mapped.IsEmpty()) m_Type = std::move(mapped); } LoadKids(pDict); }
std::unique_ptr<CPDF_Object> CPDF_StreamParser::ReadNextObject( bool bAllowNestedArray, bool bInArray, uint32_t dwRecursionLevel) { bool bIsNumber; // Must get the next word before returning to avoid infinite loops. GetNextWord(bIsNumber); if (!m_WordSize || dwRecursionLevel > kMaxNestedParsingLevel) return nullptr; if (bIsNumber) { m_WordBuffer[m_WordSize] = 0; return pdfium::MakeUnique<CPDF_Number>( ByteStringView(m_WordBuffer, m_WordSize)); } int first_char = m_WordBuffer[0]; if (first_char == '/') { ByteString name = PDF_NameDecode(ByteStringView(m_WordBuffer + 1, m_WordSize - 1)); return pdfium::MakeUnique<CPDF_Name>(m_pPool, name); } if (first_char == '(') { ByteString str = ReadString(); return pdfium::MakeUnique<CPDF_String>(m_pPool, str, false); } if (first_char == '<') { if (m_WordSize == 1) return pdfium::MakeUnique<CPDF_String>(m_pPool, ReadHexString(), true); auto pDict = pdfium::MakeUnique<CPDF_Dictionary>(m_pPool); while (1) { GetNextWord(bIsNumber); if (m_WordSize == 2 && m_WordBuffer[0] == '>') break; if (!m_WordSize || m_WordBuffer[0] != '/') return nullptr; ByteString key = PDF_NameDecode(ByteStringView(m_WordBuffer + 1, m_WordSize - 1)); std::unique_ptr<CPDF_Object> pObj = ReadNextObject(true, bInArray, dwRecursionLevel + 1); if (!pObj) return nullptr; if (!key.IsEmpty()) pDict->SetFor(key, std::move(pObj)); } return std::move(pDict); } if (first_char == '[') { if ((!bAllowNestedArray && bInArray)) return nullptr; auto pArray = pdfium::MakeUnique<CPDF_Array>(); while (1) { std::unique_ptr<CPDF_Object> pObj = ReadNextObject(bAllowNestedArray, true, dwRecursionLevel + 1); if (pObj) { pArray->Add(std::move(pObj)); continue; } if (!m_WordSize || m_WordBuffer[0] == ']') break; } return std::move(pArray); } if (m_WordSize == 5 && !memcmp(m_WordBuffer, "false", 5)) return pdfium::MakeUnique<CPDF_Boolean>(false); if (m_WordSize == 4) { if (memcmp(m_WordBuffer, "true", 4) == 0) return pdfium::MakeUnique<CPDF_Boolean>(true); if (memcmp(m_WordBuffer, "null", 4) == 0) return pdfium::MakeUnique<CPDF_Null>(); } return nullptr; }
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)); }