1 // Copyright 2017 The PDFium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #include "core/fxcrt/cfx_memorystream.h" 8 9 #include <algorithm> 10 #include <utility> 11 12 #include "core/fxcrt/fx_safe_types.h" 13 #include "core/fxcrt/stl_util.h" 14 15 CFX_MemoryStream::CFX_MemoryStream() = default; 16 17 CFX_MemoryStream::~CFX_MemoryStream() = default; 18 GetSize()19FX_FILESIZE CFX_MemoryStream::GetSize() { 20 return static_cast<FX_FILESIZE>(m_nCurSize); 21 } 22 IsEOF()23bool CFX_MemoryStream::IsEOF() { 24 return m_nCurPos >= static_cast<size_t>(GetSize()); 25 } 26 GetPosition()27FX_FILESIZE CFX_MemoryStream::GetPosition() { 28 return static_cast<FX_FILESIZE>(m_nCurPos); 29 } 30 Flush()31bool CFX_MemoryStream::Flush() { 32 return true; 33 } 34 GetSpan() const35pdfium::span<const uint8_t> CFX_MemoryStream::GetSpan() const { 36 return pdfium::make_span(m_data).first(m_nCurSize); 37 } 38 ReadBlockAtOffset(pdfium::span<uint8_t> buffer,FX_FILESIZE offset)39bool CFX_MemoryStream::ReadBlockAtOffset(pdfium::span<uint8_t> buffer, 40 FX_FILESIZE offset) { 41 if (buffer.empty() || offset < 0) 42 return false; 43 44 FX_SAFE_SIZE_T new_pos = buffer.size(); 45 new_pos += offset; 46 if (!new_pos.IsValid() || new_pos.ValueOrDefault(0) == 0 || 47 new_pos.ValueOrDie() > m_nCurSize) { 48 return false; 49 } 50 51 m_nCurPos = new_pos.ValueOrDie(); 52 // Safe to cast `offset` because it was used to calculate `new_pos` above, and 53 // `new_pos` is valid. 54 fxcrt::Copy(GetSpan().subspan(static_cast<size_t>(offset), buffer.size()), 55 buffer); 56 return true; 57 } 58 WriteBlock(pdfium::span<const uint8_t> buffer)59bool CFX_MemoryStream::WriteBlock(pdfium::span<const uint8_t> buffer) { 60 if (buffer.empty()) 61 return true; 62 63 FX_SAFE_SIZE_T safe_new_pos = buffer.size(); 64 safe_new_pos += m_nCurSize; 65 if (!safe_new_pos.IsValid()) { 66 return false; 67 } 68 69 size_t new_pos = safe_new_pos.ValueOrDie(); 70 if (new_pos > m_data.size()) { 71 static constexpr size_t kBlockSize = 64 * 1024; 72 FX_SAFE_SIZE_T new_size = new_pos; 73 new_size *= 2; 74 new_size += (kBlockSize - 1); 75 new_size /= kBlockSize; 76 new_size *= kBlockSize; 77 if (!new_size.IsValid()) 78 return false; 79 80 m_data.resize(new_size.ValueOrDie()); 81 } 82 m_nCurPos = new_pos; 83 84 fxcrt::Copy(buffer, pdfium::make_span(m_data).subspan(m_nCurSize)); 85 m_nCurSize = std::max(m_nCurSize, m_nCurPos); 86 87 return true; 88 } 89