Пример #1
0
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);
}
Пример #2
0
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;
}
Пример #3
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));
}